mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/ata/libata-scsi.c include/linux/libata.h Futher merge of Linus's head and compilation fixups. Signed-Off-By: David Howells <[email protected]>
This commit is contained in:
commit
9db7372445
588 changed files with 32298 additions and 9297 deletions
|
|
@ -77,3 +77,4 @@ obj-$(CONFIG_CRYPTO) += crypto/
|
|||
obj-$(CONFIG_SUPERH) += sh/
|
||||
obj-$(CONFIG_GENERIC_TIME) += clocksource/
|
||||
obj-$(CONFIG_DMA_ENGINE) += dma/
|
||||
obj-$(CONFIG_PPC_PS3) += ps3/
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -328,6 +328,15 @@ config PATA_TRIFLEX
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_MARVELL
|
||||
tristate "Marvell PATA support via legacy mode"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables limited support for the Marvell 88SE6145 ATA
|
||||
controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_MPIIX
|
||||
tristate "Intel PATA MPIIX support"
|
||||
depends on PCI
|
||||
|
|
@ -483,6 +492,32 @@ config PATA_WINBOND
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_WINBOND_VLB
|
||||
tristate "Winbond W83759A VLB PATA support (Experimental)"
|
||||
depends on ISA && EXPERIMENTAL
|
||||
help
|
||||
Support for the Winbond W83759A controller on Vesa Local Bus
|
||||
systems.
|
||||
|
||||
config PATA_PLATFORM
|
||||
tristate "Generic platform device PATA support"
|
||||
depends on EMBEDDED
|
||||
help
|
||||
This option enables support for generic directly connected ATA
|
||||
devices commonly found on embedded systems.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_IXP4XX_CF
|
||||
tristate "IXP4XX Compact Flash support"
|
||||
depends on ARCH_IXP4XX
|
||||
help
|
||||
This option enables support for a Compact Flash connected on
|
||||
the ixp4xx expansion bus. This driver had been written for
|
||||
Loft/Avila boards in mind but can work with others.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endif
|
||||
endmenu
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
|
|||
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
|
||||
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
|
||||
obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
|
||||
obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o
|
||||
obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
|
||||
obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
|
||||
obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
|
||||
|
|
@ -51,8 +52,11 @@ obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
|
|||
obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
|
||||
obj-$(CONFIG_PATA_VIA) += pata_via.o
|
||||
obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
|
||||
obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
|
||||
obj-$(CONFIG_PATA_SIS) += pata_sis.o
|
||||
obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
|
||||
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
|
||||
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
|
||||
# Should be last but one libata driver
|
||||
obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
|
||||
# Should be last libata driver
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
enum {
|
||||
AHCI_PCI_BAR = 5,
|
||||
AHCI_MAX_PORTS = 32,
|
||||
AHCI_MAX_SG = 168, /* hardware max is 64K */
|
||||
AHCI_DMA_BOUNDARY = 0xffffffff,
|
||||
AHCI_USE_CLUSTERING = 0,
|
||||
|
|
@ -77,8 +78,9 @@ enum {
|
|||
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
|
||||
|
||||
board_ahci = 0,
|
||||
board_ahci_vt8251 = 1,
|
||||
board_ahci_ign_iferr = 2,
|
||||
board_ahci_pi = 1,
|
||||
board_ahci_vt8251 = 2,
|
||||
board_ahci_ign_iferr = 3,
|
||||
|
||||
/* global controller registers */
|
||||
HOST_CAP = 0x00, /* host capabilities */
|
||||
|
|
@ -167,9 +169,9 @@ enum {
|
|||
AHCI_FLAG_MSI = (1 << 0),
|
||||
|
||||
/* ap->flags bits */
|
||||
AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24),
|
||||
AHCI_FLAG_NO_NCQ = (1 << 25),
|
||||
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */
|
||||
AHCI_FLAG_NO_NCQ = (1 << 24),
|
||||
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
|
||||
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
|
||||
};
|
||||
|
||||
struct ahci_cmd_hdr {
|
||||
|
|
@ -216,6 +218,7 @@ static u8 ahci_check_status(struct ata_port *ap);
|
|||
static void ahci_freeze(struct ata_port *ap);
|
||||
static void ahci_thaw(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_post_internal_cmd(struct ata_queued_cmd *qc);
|
||||
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
|
||||
static int ahci_port_resume(struct ata_port *ap);
|
||||
|
|
@ -275,6 +278,37 @@ static const struct ata_port_operations ahci_ops = {
|
|||
.port_stop = ahci_port_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations ahci_vt8251_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
|
||||
.check_status = ahci_check_status,
|
||||
.check_altstatus = ahci_check_status,
|
||||
.dev_select = ata_noop_dev_select,
|
||||
|
||||
.tf_read = ahci_tf_read,
|
||||
|
||||
.qc_prep = ahci_qc_prep,
|
||||
.qc_issue = ahci_qc_issue,
|
||||
|
||||
.irq_handler = ahci_interrupt,
|
||||
.irq_clear = ahci_irq_clear,
|
||||
|
||||
.scr_read = ahci_scr_read,
|
||||
.scr_write = ahci_scr_write,
|
||||
|
||||
.freeze = ahci_freeze,
|
||||
.thaw = ahci_thaw,
|
||||
|
||||
.error_handler = ahci_vt8251_error_handler,
|
||||
.post_internal_cmd = ahci_post_internal_cmd,
|
||||
|
||||
.port_suspend = ahci_port_suspend,
|
||||
.port_resume = ahci_port_resume,
|
||||
|
||||
.port_start = ahci_port_start,
|
||||
.port_stop = ahci_port_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_info ahci_port_info[] = {
|
||||
/* board_ahci */
|
||||
{
|
||||
|
|
@ -286,16 +320,26 @@ static const struct ata_port_info ahci_port_info[] = {
|
|||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
/* board_ahci_pi */
|
||||
{
|
||||
.sht = &ahci_sht,
|
||||
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
/* board_ahci_vt8251 */
|
||||
{
|
||||
.sht = &ahci_sht,
|
||||
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_SKIP_D2H_BSY |
|
||||
AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
|
||||
ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &ahci_ops,
|
||||
.port_ops = &ahci_vt8251_ops,
|
||||
},
|
||||
/* board_ahci_ign_iferr */
|
||||
{
|
||||
|
|
@ -322,22 +366,22 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
|
||||
{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
|
||||
{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
|
||||
{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
|
||||
{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */
|
||||
{ PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */
|
||||
{ PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */
|
||||
{ PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */
|
||||
{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */
|
||||
|
||||
/* JMicron */
|
||||
{ PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
|
||||
|
|
@ -372,6 +416,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
|
||||
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
|
||||
|
||||
/* Generic, PCI class code for AHCI */
|
||||
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
0x010601, 0xffffff, board_ahci },
|
||||
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
|
|
@ -386,6 +434,11 @@ static struct pci_driver ahci_pci_driver = {
|
|||
};
|
||||
|
||||
|
||||
static inline int ahci_nr_ports(u32 cap)
|
||||
{
|
||||
return (cap & 0x1f) + 1;
|
||||
}
|
||||
|
||||
static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
|
||||
{
|
||||
return base + 0x100 + (port * 0x80);
|
||||
|
|
@ -559,9 +612,6 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
|
|||
static void ahci_init_port(void __iomem *port_mmio, u32 cap,
|
||||
dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
|
||||
{
|
||||
/* power up */
|
||||
ahci_power_up(port_mmio, cap);
|
||||
|
||||
/* enable FIS reception */
|
||||
ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
|
||||
|
||||
|
|
@ -587,19 +637,17 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* put device into slumber mode */
|
||||
ahci_power_down(port_mmio, cap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
|
||||
{
|
||||
u32 cap_save, tmp;
|
||||
u32 cap_save, impl_save, tmp;
|
||||
|
||||
cap_save = readl(mmio + HOST_CAP);
|
||||
cap_save &= ( (1<<28) | (1<<17) );
|
||||
cap_save |= (1 << 27);
|
||||
impl_save = readl(mmio + HOST_PORTS_IMPL);
|
||||
|
||||
/* global controller reset */
|
||||
tmp = readl(mmio + HOST_CTL);
|
||||
|
|
@ -620,10 +668,21 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* turn on AHCI mode */
|
||||
writel(HOST_AHCI_EN, mmio + HOST_CTL);
|
||||
(void) readl(mmio + HOST_CTL); /* flush */
|
||||
|
||||
/* These write-once registers are normally cleared on reset.
|
||||
* Restore BIOS values... which we HOPE were present before
|
||||
* reset.
|
||||
*/
|
||||
if (!impl_save) {
|
||||
impl_save = (1 << ahci_nr_ports(cap_save)) - 1;
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"PORTS_IMPL is zero, forcing 0x%x\n", impl_save);
|
||||
}
|
||||
writel(cap_save, mmio + HOST_CAP);
|
||||
writel(0xf, mmio + HOST_PORTS_IMPL);
|
||||
writel(impl_save, mmio + HOST_PORTS_IMPL);
|
||||
(void) readl(mmio + HOST_PORTS_IMPL); /* flush */
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
|
|
@ -639,7 +698,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
|
||||
int n_ports, u32 cap)
|
||||
int n_ports, unsigned int port_flags,
|
||||
struct ahci_host_priv *hpriv)
|
||||
{
|
||||
int i, rc;
|
||||
u32 tmp;
|
||||
|
|
@ -648,13 +708,12 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|||
void __iomem *port_mmio = ahci_port_base(mmio, i);
|
||||
const char *emsg = NULL;
|
||||
|
||||
#if 0 /* BIOSen initialize this incorrectly */
|
||||
if (!(hpriv->port_map & (1 << i)))
|
||||
if ((port_flags & AHCI_FLAG_HONOR_PI) &&
|
||||
!(hpriv->port_map & (1 << i)))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* make sure port is not active */
|
||||
rc = ahci_deinit_port(port_mmio, cap, &emsg);
|
||||
rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
if (rc)
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"%s (%d)\n", emsg, rc);
|
||||
|
|
@ -729,17 +788,6 @@ static int ahci_clo(struct ata_port *ap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ahci_prereset(struct ata_port *ap)
|
||||
{
|
||||
if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
|
||||
(ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
|
||||
/* ATA_BUSY hasn't cleared, so send a CLO */
|
||||
ahci_clo(ap);
|
||||
}
|
||||
|
||||
return ata_std_prereset(ap);
|
||||
}
|
||||
|
||||
static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
||||
{
|
||||
struct ahci_port_priv *pp = ap->private_data;
|
||||
|
|
@ -877,6 +925,31 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
|
||||
{
|
||||
void __iomem *mmio = ap->host->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
ahci_stop_engine(port_mmio);
|
||||
|
||||
rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
|
||||
|
||||
/* vt8251 needs SError cleared for the port to operate */
|
||||
ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
|
||||
|
||||
ahci_start_engine(port_mmio);
|
||||
|
||||
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
|
||||
|
||||
/* vt8251 doesn't clear BSY on signature FIS reception,
|
||||
* request follow-up softreset.
|
||||
*/
|
||||
return rc ?: -EAGAIN;
|
||||
}
|
||||
|
||||
static void ahci_postreset(struct ata_port *ap, unsigned int *class)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
|
|
@ -1196,7 +1269,23 @@ static void ahci_error_handler(struct ata_port *ap)
|
|||
}
|
||||
|
||||
/* perform recovery */
|
||||
ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
|
||||
ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset,
|
||||
ahci_postreset);
|
||||
}
|
||||
|
||||
static void ahci_vt8251_error_handler(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->host->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
|
||||
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
||||
/* restart engine */
|
||||
ahci_stop_engine(port_mmio);
|
||||
ahci_start_engine(port_mmio);
|
||||
}
|
||||
|
||||
/* perform recovery */
|
||||
ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
|
||||
ahci_postreset);
|
||||
}
|
||||
|
||||
|
|
@ -1226,7 +1315,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
|||
int rc;
|
||||
|
||||
rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
if (rc) {
|
||||
if (rc == 0)
|
||||
ahci_power_down(port_mmio, hpriv->cap);
|
||||
else {
|
||||
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
|
||||
ahci_init_port(port_mmio, hpriv->cap,
|
||||
pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
|
|
@ -1242,6 +1333,7 @@ static int ahci_port_resume(struct ata_port *ap)
|
|||
void __iomem *mmio = ap->host->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
|
||||
ahci_power_up(port_mmio, hpriv->cap);
|
||||
ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1281,7 +1373,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap);
|
||||
ahci_init_controller(mmio, pdev, host->n_ports,
|
||||
host->ports[0]->flags, hpriv);
|
||||
}
|
||||
|
||||
ata_host_resume(host);
|
||||
|
|
@ -1347,6 +1440,9 @@ static int ahci_port_start(struct ata_port *ap)
|
|||
|
||||
ap->private_data = pp;
|
||||
|
||||
/* power up port */
|
||||
ahci_power_up(port_mmio, hpriv->cap);
|
||||
|
||||
/* initialize port */
|
||||
ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
|
||||
|
|
@ -1393,7 +1489,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
|
|||
struct ahci_host_priv *hpriv = probe_ent->private_data;
|
||||
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
|
||||
void __iomem *mmio = probe_ent->mmio_base;
|
||||
unsigned int i, using_dac;
|
||||
unsigned int i, cap_n_ports, using_dac;
|
||||
int rc;
|
||||
|
||||
rc = ahci_reset_controller(mmio, pdev);
|
||||
|
|
@ -1402,10 +1498,34 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
|
|||
|
||||
hpriv->cap = readl(mmio + HOST_CAP);
|
||||
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
|
||||
probe_ent->n_ports = (hpriv->cap & 0x1f) + 1;
|
||||
cap_n_ports = ahci_nr_ports(hpriv->cap);
|
||||
|
||||
VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n",
|
||||
hpriv->cap, hpriv->port_map, probe_ent->n_ports);
|
||||
hpriv->cap, hpriv->port_map, cap_n_ports);
|
||||
|
||||
if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
|
||||
unsigned int n_ports = cap_n_ports;
|
||||
u32 port_map = hpriv->port_map;
|
||||
int max_port = 0;
|
||||
|
||||
for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
|
||||
if (port_map & (1 << i)) {
|
||||
n_ports--;
|
||||
port_map &= ~(1 << i);
|
||||
max_port = i;
|
||||
} else
|
||||
probe_ent->dummy_port_mask |= 1 << i;
|
||||
}
|
||||
|
||||
if (n_ports || port_map)
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"nr_ports (%u) and implemented port map "
|
||||
"(0x%x) don't match\n",
|
||||
cap_n_ports, hpriv->port_map);
|
||||
|
||||
probe_ent->n_ports = max_port + 1;
|
||||
} else
|
||||
probe_ent->n_ports = cap_n_ports;
|
||||
|
||||
using_dac = hpriv->cap & HOST_CAP_64;
|
||||
if (using_dac &&
|
||||
|
|
@ -1437,7 +1557,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
|
|||
for (i = 0; i < probe_ent->n_ports; i++)
|
||||
ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
|
||||
|
||||
ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
|
||||
ahci_init_controller(mmio, pdev, probe_ent->n_ports,
|
||||
probe_ent->port_flags, hpriv);
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "ata_generic"
|
||||
#define DRV_VERSION "0.2.6"
|
||||
#define DRV_VERSION "0.2.10"
|
||||
|
||||
/*
|
||||
* A generic parallel ATA driver using libata
|
||||
|
|
@ -109,7 +109,6 @@ static struct scsi_host_template generic_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -118,6 +117,8 @@ static struct scsi_host_template generic_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations generic_port_ops = {
|
||||
|
|
@ -226,12 +227,14 @@ static struct pci_driver ata_generic_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = ata_generic,
|
||||
.probe = ata_generic_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init ata_generic_init(void)
|
||||
{
|
||||
return pci_module_init(&ata_generic_pci_driver);
|
||||
return pci_register_driver(&ata_generic_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
* Documentation
|
||||
* Publically available from Intel web site. Errata documentation
|
||||
* is also publically available. As an aide to anyone hacking on this
|
||||
* driver the list of errata that are relevant is below.going back to
|
||||
* driver the list of errata that are relevant is below, going back to
|
||||
* PIIX4. Older device documentation is now a bit tricky to find.
|
||||
*
|
||||
* The chipsets all follow very much the same design. The orginal Triton
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "ata_piix"
|
||||
#define DRV_VERSION "2.00ac6"
|
||||
#define DRV_VERSION "2.00ac7"
|
||||
|
||||
enum {
|
||||
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
|
||||
|
|
@ -101,11 +101,13 @@ enum {
|
|||
ICH5_PCS = 0x92, /* port control and status */
|
||||
PIIX_SCC = 0x0A, /* sub-class code register */
|
||||
|
||||
PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */
|
||||
PIIX_FLAG_SCR = (1 << 26), /* SCR available */
|
||||
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
|
||||
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
|
||||
|
||||
PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
|
||||
PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
|
||||
|
||||
/* combined mode. if set, PATA is channel 0.
|
||||
* if clear, PATA is channel 1.
|
||||
*/
|
||||
|
|
@ -122,11 +124,10 @@ enum {
|
|||
ich_pata_100 = 3, /* ICH up to UDMA 100 */
|
||||
ich_pata_133 = 4, /* ICH up to UDMA 133 */
|
||||
ich5_sata = 5,
|
||||
esb_sata = 6,
|
||||
ich6_sata = 7,
|
||||
ich6_sata_ahci = 8,
|
||||
ich6m_sata_ahci = 9,
|
||||
ich8_sata_ahci = 10,
|
||||
ich6_sata = 6,
|
||||
ich6_sata_ahci = 7,
|
||||
ich6m_sata_ahci = 8,
|
||||
ich8_sata_ahci = 9,
|
||||
|
||||
/* constants for mapping table */
|
||||
P0 = 0, /* port 0 */
|
||||
|
|
@ -143,13 +144,11 @@ enum {
|
|||
struct piix_map_db {
|
||||
const u32 mask;
|
||||
const u16 port_enable;
|
||||
const int present_shift;
|
||||
const int map[][4];
|
||||
};
|
||||
|
||||
struct piix_host_priv {
|
||||
const int *map;
|
||||
const struct piix_map_db *map_db;
|
||||
};
|
||||
|
||||
static int piix_init_one (struct pci_dev *pdev,
|
||||
|
|
@ -214,9 +213,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
|
|||
/* 82801EB (ICH5) */
|
||||
{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
/* 6300ESB (ICH5 variant with broken PCS present bits) */
|
||||
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
|
||||
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
/* 6300ESB pretending RAID */
|
||||
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
|
||||
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
/* 82801FB/FW (ICH6/ICH6W) */
|
||||
{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
|
||||
/* 82801FR/FRW (ICH6R/ICH6RW) */
|
||||
|
|
@ -367,7 +366,6 @@ static const struct ata_port_operations piix_sata_ops = {
|
|||
static const struct piix_map_db ich5_map_db = {
|
||||
.mask = 0x7,
|
||||
.port_enable = 0x3,
|
||||
.present_shift = 4,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, NA, P1, NA }, /* 000b */
|
||||
|
|
@ -384,7 +382,6 @@ static const struct piix_map_db ich5_map_db = {
|
|||
static const struct piix_map_db ich6_map_db = {
|
||||
.mask = 0x3,
|
||||
.port_enable = 0xf,
|
||||
.present_shift = 4,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, P2, P1, P3 }, /* 00b */
|
||||
|
|
@ -397,7 +394,6 @@ static const struct piix_map_db ich6_map_db = {
|
|||
static const struct piix_map_db ich6m_map_db = {
|
||||
.mask = 0x3,
|
||||
.port_enable = 0x5,
|
||||
.present_shift = 4,
|
||||
|
||||
/* Map 01b isn't specified in the doc but some notebooks use
|
||||
* it anyway. MAP 01b have been spotted on both ICH6M and
|
||||
|
|
@ -415,7 +411,6 @@ static const struct piix_map_db ich6m_map_db = {
|
|||
static const struct piix_map_db ich8_map_db = {
|
||||
.mask = 0x3,
|
||||
.port_enable = 0x3,
|
||||
.present_shift = 8,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */
|
||||
|
|
@ -427,7 +422,6 @@ static const struct piix_map_db ich8_map_db = {
|
|||
|
||||
static const struct piix_map_db *piix_map_db_table[] = {
|
||||
[ich5_sata] = &ich5_map_db,
|
||||
[esb_sata] = &ich5_map_db,
|
||||
[ich6_sata] = &ich6_map_db,
|
||||
[ich6_sata_ahci] = &ich6_map_db,
|
||||
[ich6m_sata_ahci] = &ich6m_map_db,
|
||||
|
|
@ -438,7 +432,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* piix_pata_33: 0: PIIX3 or 4 at 33MHz */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = PIIX_PATA_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
|
||||
.udma_mask = ATA_UDMA_MASK_40C,
|
||||
|
|
@ -448,7 +442,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
|
||||
.flags = PIIX_PATA_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio 0-4 */
|
||||
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
|
||||
.udma_mask = ATA_UDMA2, /* UDMA33 */
|
||||
|
|
@ -457,7 +451,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich_pata_66: 2 ICH controllers up to 66MHz */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
|
||||
.flags = PIIX_PATA_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio 0-4 */
|
||||
.mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
|
||||
.udma_mask = ATA_UDMA4,
|
||||
|
|
@ -467,7 +461,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich_pata_100: 3 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
|
||||
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x06, /* mwdma1-2 */
|
||||
.udma_mask = ATA_UDMA5, /* udma0-5 */
|
||||
|
|
@ -477,7 +471,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich_pata_133: 4 ICH with full UDMA6 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
|
||||
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
|
||||
.pio_mask = 0x1f, /* pio 0-4 */
|
||||
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
|
||||
.udma_mask = ATA_UDMA6, /* UDMA133 */
|
||||
|
|
@ -487,41 +481,27 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich5_sata: 5 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
|
||||
PIIX_FLAG_IGNORE_PCS,
|
||||
.flags = PIIX_SATA_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
},
|
||||
|
||||
/* i6300esb_sata: 6 */
|
||||
/* ich6_sata: 6 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
|
||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
},
|
||||
|
||||
/* ich6_sata: 7 */
|
||||
/* ich6_sata_ahci: 7 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
},
|
||||
|
||||
/* ich6_sata_ahci: 8 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
||||
PIIX_FLAG_AHCI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
|
|
@ -529,11 +509,10 @@ static struct ata_port_info piix_port_info[] = {
|
|||
.port_ops = &piix_sata_ops,
|
||||
},
|
||||
|
||||
/* ich6m_sata_ahci: 9 */
|
||||
/* ich6m_sata_ahci: 8 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
||||
PIIX_FLAG_AHCI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
|
|
@ -541,11 +520,10 @@ static struct ata_port_info piix_port_info[] = {
|
|||
.port_ops = &piix_sata_ops,
|
||||
},
|
||||
|
||||
/* ich8_sata_ahci: 10 */
|
||||
/* ich8_sata_ahci: 9 */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.flags = ATA_FLAG_SATA |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
||||
PIIX_FLAG_AHCI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
|
|
@ -566,10 +544,22 @@ MODULE_LICENSE("GPL");
|
|||
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
static int force_pcs = 0;
|
||||
module_param(force_pcs, int, 0444);
|
||||
MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
|
||||
"device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
|
||||
struct ich_laptop {
|
||||
u16 device;
|
||||
u16 subvendor;
|
||||
u16 subdevice;
|
||||
};
|
||||
|
||||
/*
|
||||
* List of laptops that use short cables rather than 80 wire
|
||||
*/
|
||||
|
||||
static const struct ich_laptop ich_laptop[] = {
|
||||
/* devid, subvendor, subdev */
|
||||
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
|
||||
/* end marker */
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
/**
|
||||
* piix_pata_cbl_detect - Probe host controller cable detect info
|
||||
|
|
@ -585,12 +575,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
|
|||
static void ich_pata_cbl_detect(struct ata_port *ap)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
const struct ich_laptop *lap = &ich_laptop[0];
|
||||
u8 tmp, mask;
|
||||
|
||||
/* no 80c support in host controller? */
|
||||
if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
|
||||
goto cbl40;
|
||||
|
||||
/* Check for specials - Acer Aspire 5602WLMi */
|
||||
while (lap->device) {
|
||||
if (lap->device == pdev->device &&
|
||||
lap->subvendor == pdev->subsystem_vendor &&
|
||||
lap->subdevice == pdev->subsystem_device) {
|
||||
ap->cbl = ATA_CBL_PATA40_SHORT;
|
||||
return;
|
||||
}
|
||||
lap++;
|
||||
}
|
||||
|
||||
/* check BIOS cable detect results */
|
||||
mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
|
||||
pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
|
||||
|
|
@ -659,84 +661,9 @@ static void ich_pata_error_handler(struct ata_port *ap)
|
|||
ata_std_postreset);
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_present_mask - determine present mask for SATA host controller
|
||||
* @ap: Target port
|
||||
*
|
||||
* Reads SATA PCI device's PCI config register Port Configuration
|
||||
* and Status (PCS) to determine port and device availability.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*
|
||||
* RETURNS:
|
||||
* determined present_mask
|
||||
*/
|
||||
static unsigned int piix_sata_present_mask(struct ata_port *ap)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
struct piix_host_priv *hpriv = ap->host->private_data;
|
||||
const unsigned int *map = hpriv->map;
|
||||
int base = 2 * ap->port_no;
|
||||
unsigned int present_mask = 0;
|
||||
int port, i;
|
||||
u16 pcs;
|
||||
|
||||
pci_read_config_word(pdev, ICH5_PCS, &pcs);
|
||||
DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
port = map[base + i];
|
||||
if (port < 0)
|
||||
continue;
|
||||
if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
|
||||
(pcs & 1 << (hpriv->map_db->present_shift + port)))
|
||||
present_mask |= 1 << i;
|
||||
}
|
||||
|
||||
DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
|
||||
ap->id, pcs, present_mask);
|
||||
|
||||
return present_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_softreset - reset SATA host port via ATA SRST
|
||||
* @ap: port to reset
|
||||
* @classes: resulting classes of attached devices
|
||||
*
|
||||
* Reset SATA host port via ATA SRST. On controllers with
|
||||
* reliable PCS present bits, the bits are used to determine
|
||||
* device presence.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
unsigned int present_mask;
|
||||
int i, rc;
|
||||
|
||||
present_mask = piix_sata_present_mask(ap);
|
||||
|
||||
rc = ata_std_softreset(ap, classes);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
if (!(present_mask & (1 << i)))
|
||||
classes[i] = ATA_DEV_NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void piix_sata_error_handler(struct ata_port *ap)
|
||||
{
|
||||
ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
|
||||
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
|
||||
ata_std_postreset);
|
||||
}
|
||||
|
||||
|
|
@ -1051,18 +978,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
|
|||
pci_write_config_word(pdev, ICH5_PCS, new_pcs);
|
||||
msleep(150);
|
||||
}
|
||||
|
||||
if (force_pcs == 1) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"force ignoring PCS (0x%x)\n", new_pcs);
|
||||
pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS;
|
||||
pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS;
|
||||
} else if (force_pcs == 2) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"force honoring PCS (0x%x)\n", new_pcs);
|
||||
pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS;
|
||||
pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS;
|
||||
}
|
||||
}
|
||||
|
||||
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||
|
|
@ -1112,7 +1027,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
|||
"invalid MAP value %u\n", map_value);
|
||||
|
||||
hpriv->map = map;
|
||||
hpriv->map_db = map_db;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -199,7 +199,8 @@ static const u8 ata_rw_cmds[] = {
|
|||
|
||||
/**
|
||||
* ata_rwcmd_protocol - set taskfile r/w commands and protocol
|
||||
* @qc: command to examine and configure
|
||||
* @tf: command to examine and configure
|
||||
* @dev: device tf belongs to
|
||||
*
|
||||
* Examine the device configuration and tf->flags to calculate
|
||||
* the proper read/write commands and protocol to use.
|
||||
|
|
@ -207,10 +208,8 @@ static const u8 ata_rw_cmds[] = {
|
|||
* LOCKING:
|
||||
* caller.
|
||||
*/
|
||||
int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
|
||||
static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev)
|
||||
{
|
||||
struct ata_taskfile *tf = &qc->tf;
|
||||
struct ata_device *dev = qc->dev;
|
||||
u8 cmd;
|
||||
|
||||
int index, fua, lba48, write;
|
||||
|
|
@ -222,7 +221,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
|
|||
if (dev->flags & ATA_DFLAG_PIO) {
|
||||
tf->protocol = ATA_PROT_PIO;
|
||||
index = dev->multi_count ? 0 : 8;
|
||||
} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
|
||||
} else if (lba48 && (dev->ap->flags & ATA_FLAG_PIO_LBA48)) {
|
||||
/* Unable to use DMA due to host limitation */
|
||||
tf->protocol = ATA_PROT_PIO;
|
||||
index = dev->multi_count ? 0 : 8;
|
||||
|
|
@ -239,6 +238,174 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_tf_read_block - Read block address from ATA taskfile
|
||||
* @tf: ATA taskfile of interest
|
||||
* @dev: ATA device @tf belongs to
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* Read block address from @tf. This function can handle all
|
||||
* three address formats - LBA, LBA48 and CHS. tf->protocol and
|
||||
* flags select the address format to use.
|
||||
*
|
||||
* RETURNS:
|
||||
* Block address read from @tf.
|
||||
*/
|
||||
u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
|
||||
{
|
||||
u64 block = 0;
|
||||
|
||||
if (tf->flags & ATA_TFLAG_LBA) {
|
||||
if (tf->flags & ATA_TFLAG_LBA48) {
|
||||
block |= (u64)tf->hob_lbah << 40;
|
||||
block |= (u64)tf->hob_lbam << 32;
|
||||
block |= tf->hob_lbal << 24;
|
||||
} else
|
||||
block |= (tf->device & 0xf) << 24;
|
||||
|
||||
block |= tf->lbah << 16;
|
||||
block |= tf->lbam << 8;
|
||||
block |= tf->lbal;
|
||||
} else {
|
||||
u32 cyl, head, sect;
|
||||
|
||||
cyl = tf->lbam | (tf->lbah << 8);
|
||||
head = tf->device & 0xf;
|
||||
sect = tf->lbal;
|
||||
|
||||
block = (cyl * dev->heads + head) * dev->sectors + sect;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_build_rw_tf - Build ATA taskfile for given read/write request
|
||||
* @tf: Target ATA taskfile
|
||||
* @dev: ATA device @tf belongs to
|
||||
* @block: Block address
|
||||
* @n_block: Number of blocks
|
||||
* @tf_flags: RW/FUA etc...
|
||||
* @tag: tag
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* Build ATA taskfile @tf for read/write request described by
|
||||
* @block, @n_block, @tf_flags and @tag on @dev.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success, -ERANGE if the request is too large for @dev,
|
||||
* -EINVAL if the request is invalid.
|
||||
*/
|
||||
int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||
u64 block, u32 n_block, unsigned int tf_flags,
|
||||
unsigned int tag)
|
||||
{
|
||||
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
|
||||
tf->flags |= tf_flags;
|
||||
|
||||
if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
|
||||
ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ &&
|
||||
likely(tag != ATA_TAG_INTERNAL)) {
|
||||
/* yay, NCQ */
|
||||
if (!lba_48_ok(block, n_block))
|
||||
return -ERANGE;
|
||||
|
||||
tf->protocol = ATA_PROT_NCQ;
|
||||
tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
|
||||
|
||||
if (tf->flags & ATA_TFLAG_WRITE)
|
||||
tf->command = ATA_CMD_FPDMA_WRITE;
|
||||
else
|
||||
tf->command = ATA_CMD_FPDMA_READ;
|
||||
|
||||
tf->nsect = tag << 3;
|
||||
tf->hob_feature = (n_block >> 8) & 0xff;
|
||||
tf->feature = n_block & 0xff;
|
||||
|
||||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
tf->lbah = (block >> 16) & 0xff;
|
||||
tf->lbam = (block >> 8) & 0xff;
|
||||
tf->lbal = block & 0xff;
|
||||
|
||||
tf->device = 1 << 6;
|
||||
if (tf->flags & ATA_TFLAG_FUA)
|
||||
tf->device |= 1 << 7;
|
||||
} else if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
|
||||
if (lba_28_ok(block, n_block)) {
|
||||
/* use LBA28 */
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
} else if (lba_48_ok(block, n_block)) {
|
||||
if (!(dev->flags & ATA_DFLAG_LBA48))
|
||||
return -ERANGE;
|
||||
|
||||
/* use LBA48 */
|
||||
tf->flags |= ATA_TFLAG_LBA48;
|
||||
|
||||
tf->hob_nsect = (n_block >> 8) & 0xff;
|
||||
|
||||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
} else
|
||||
/* request too large even for LBA48 */
|
||||
return -ERANGE;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
tf->nsect = n_block & 0xff;
|
||||
|
||||
tf->lbah = (block >> 16) & 0xff;
|
||||
tf->lbam = (block >> 8) & 0xff;
|
||||
tf->lbal = block & 0xff;
|
||||
|
||||
tf->device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
u32 sect, head, cyl, track;
|
||||
|
||||
/* The request -may- be too large for CHS addressing. */
|
||||
if (!lba_28_ok(block, n_block))
|
||||
return -ERANGE;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* Convert LBA to CHS */
|
||||
track = (u32)block / dev->sectors;
|
||||
cyl = track / dev->heads;
|
||||
head = track % dev->heads;
|
||||
sect = (u32)block % dev->sectors + 1;
|
||||
|
||||
DPRINTK("block %u track %u cyl %u head %u sect %u\n",
|
||||
(u32)block, track, cyl, head, sect);
|
||||
|
||||
/* Check whether the converted CHS can fit.
|
||||
Cylinder: 0-65535
|
||||
Head: 0-15
|
||||
Sector: 1-255*/
|
||||
if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
|
||||
return -ERANGE;
|
||||
|
||||
tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
|
||||
tf->lbal = sect;
|
||||
tf->lbam = cyl;
|
||||
tf->lbah = cyl >> 8;
|
||||
tf->device |= head;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
|
||||
* @pio_mask: pio_mask
|
||||
|
|
@ -997,13 +1164,13 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
|
|||
}
|
||||
|
||||
/**
|
||||
* ata_exec_internal - execute libata internal command
|
||||
* ata_exec_internal_sg - execute libata internal command
|
||||
* @dev: Device to which the command is sent
|
||||
* @tf: Taskfile registers for the command and the result
|
||||
* @cdb: CDB for packet command
|
||||
* @dma_dir: Data tranfer direction of the command
|
||||
* @buf: Data buffer of the command
|
||||
* @buflen: Length of data buffer
|
||||
* @sg: sg list for the data buffer of the command
|
||||
* @n_elem: Number of sg entries
|
||||
*
|
||||
* Executes libata internal command with timeout. @tf contains
|
||||
* command on entry and result on return. Timeout and error
|
||||
|
|
@ -1017,9 +1184,10 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
|
|||
* RETURNS:
|
||||
* Zero on success, AC_ERR_* mask on failure
|
||||
*/
|
||||
unsigned ata_exec_internal(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, void *buf, unsigned int buflen)
|
||||
unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, struct scatterlist *sg,
|
||||
unsigned int n_elem)
|
||||
{
|
||||
struct ata_port *ap = dev->ap;
|
||||
u8 command = tf->command;
|
||||
|
|
@ -1075,7 +1243,12 @@ unsigned ata_exec_internal(struct ata_device *dev,
|
|||
qc->flags |= ATA_QCFLAG_RESULT_TF;
|
||||
qc->dma_dir = dma_dir;
|
||||
if (dma_dir != DMA_NONE) {
|
||||
ata_sg_init_one(qc, buf, buflen);
|
||||
unsigned int i, buflen = 0;
|
||||
|
||||
for (i = 0; i < n_elem; i++)
|
||||
buflen += sg[i].length;
|
||||
|
||||
ata_sg_init(qc, sg, n_elem);
|
||||
qc->nsect = buflen / ATA_SECT_SIZE;
|
||||
}
|
||||
|
||||
|
|
@ -1158,6 +1331,35 @@ unsigned ata_exec_internal(struct ata_device *dev,
|
|||
return err_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_exec_internal_sg - execute libata internal command
|
||||
* @dev: Device to which the command is sent
|
||||
* @tf: Taskfile registers for the command and the result
|
||||
* @cdb: CDB for packet command
|
||||
* @dma_dir: Data tranfer direction of the command
|
||||
* @buf: Data buffer of the command
|
||||
* @buflen: Length of data buffer
|
||||
*
|
||||
* Wrapper around ata_exec_internal_sg() which takes simple
|
||||
* buffer instead of sg list.
|
||||
*
|
||||
* LOCKING:
|
||||
* None. Should be called with kernel context, might sleep.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, AC_ERR_* mask on failure
|
||||
*/
|
||||
unsigned ata_exec_internal(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, void *buf, unsigned int buflen)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, buf, buflen);
|
||||
|
||||
return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_do_simple_cmd - execute simple internal command
|
||||
* @dev: Device to which the command is sent
|
||||
|
|
@ -1222,7 +1424,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
|
|||
* ata_dev_read_id - Read ID data from the specified device
|
||||
* @dev: target device
|
||||
* @p_class: pointer to class of the target device (may be changed)
|
||||
* @post_reset: is this read ID post-reset?
|
||||
* @flags: ATA_READID_* flags
|
||||
* @id: buffer to read IDENTIFY data into
|
||||
*
|
||||
* Read ID data from the specified device. ATA_CMD_ID_ATA is
|
||||
|
|
@ -1237,7 +1439,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
|
|||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
||||
int post_reset, u16 *id)
|
||||
unsigned int flags, u16 *id)
|
||||
{
|
||||
struct ata_port *ap = dev->ap;
|
||||
unsigned int class = *p_class;
|
||||
|
|
@ -1269,10 +1471,17 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
|||
}
|
||||
|
||||
tf.protocol = ATA_PROT_PIO;
|
||||
tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
|
||||
id, sizeof(id[0]) * ATA_ID_WORDS);
|
||||
if (err_mask) {
|
||||
if (err_mask & AC_ERR_NODEV_HINT) {
|
||||
DPRINTK("ata%u.%d: NODEV after polling detection\n",
|
||||
ap->id, dev->devno);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rc = -EIO;
|
||||
reason = "I/O error";
|
||||
goto err_out;
|
||||
|
|
@ -1292,7 +1501,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
if (post_reset && class == ATA_DEV_ATA) {
|
||||
if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
|
||||
/*
|
||||
* The exact sequence expected by certain pre-ATA4 drives is:
|
||||
* SRST RESET
|
||||
|
|
@ -1312,7 +1521,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
|||
/* current CHS translation info (id[53-58]) might be
|
||||
* changed. reread the identify device info.
|
||||
*/
|
||||
post_reset = 0;
|
||||
flags &= ~ATA_READID_POSTRESET;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
@ -1343,7 +1552,10 @@ static void ata_dev_config_ncq(struct ata_device *dev,
|
|||
desc[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
|
||||
snprintf(desc, desc_sz, "NCQ (not used)");
|
||||
return;
|
||||
}
|
||||
if (ap->flags & ATA_FLAG_NCQ) {
|
||||
hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
|
||||
dev->flags |= ATA_DFLAG_NCQ;
|
||||
|
|
@ -1372,7 +1584,6 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap)
|
|||
/**
|
||||
* ata_dev_configure - Configure the specified ATA/ATAPI device
|
||||
* @dev: Target device to configure
|
||||
* @print_info: Enable device info printout
|
||||
*
|
||||
* Configure @dev according to @dev->id. Generic and low-level
|
||||
* driver specific fixups are also applied.
|
||||
|
|
@ -1383,9 +1594,10 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap)
|
|||
* RETURNS:
|
||||
* 0 on success, -errno otherwise
|
||||
*/
|
||||
int ata_dev_configure(struct ata_device *dev, int print_info)
|
||||
int ata_dev_configure(struct ata_device *dev)
|
||||
{
|
||||
struct ata_port *ap = dev->ap;
|
||||
int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
|
||||
const u16 *id = dev->id;
|
||||
unsigned int xfer_mask;
|
||||
char revbuf[7]; /* XYZ-99\0 */
|
||||
|
|
@ -1452,6 +1664,10 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
|
|||
if (ata_id_has_lba48(id)) {
|
||||
dev->flags |= ATA_DFLAG_LBA48;
|
||||
lba_desc = "LBA48";
|
||||
|
||||
if (dev->n_sectors >= (1UL << 28) &&
|
||||
ata_id_has_flush_ext(id))
|
||||
dev->flags |= ATA_DFLAG_FLUSH_EXT;
|
||||
}
|
||||
|
||||
/* config NCQ */
|
||||
|
|
@ -1528,6 +1744,11 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
|
|||
cdb_intr_string);
|
||||
}
|
||||
|
||||
/* determine max_sectors */
|
||||
dev->max_sectors = ATA_MAX_SECTORS;
|
||||
if (dev->flags & ATA_DFLAG_LBA48)
|
||||
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
|
||||
|
||||
if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
|
||||
/* Let the user know. We don't want to disallow opens for
|
||||
rescue purposes, or in case the vendor is just a blithering
|
||||
|
|
@ -1629,11 +1850,14 @@ int ata_bus_probe(struct ata_port *ap)
|
|||
if (!ata_dev_enabled(dev))
|
||||
continue;
|
||||
|
||||
rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
|
||||
rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET,
|
||||
dev->id);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = ata_dev_configure(dev, 1);
|
||||
ap->eh_context.i.flags |= ATA_EHI_PRINTINFO;
|
||||
rc = ata_dev_configure(dev);
|
||||
ap->eh_context.i.flags &= ~ATA_EHI_PRINTINFO;
|
||||
if (rc)
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -2151,6 +2375,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
|
|||
|
||||
static int ata_dev_set_mode(struct ata_device *dev)
|
||||
{
|
||||
struct ata_eh_context *ehc = &dev->ap->eh_context;
|
||||
unsigned int err_mask;
|
||||
int rc;
|
||||
|
||||
|
|
@ -2165,7 +2390,9 @@ static int ata_dev_set_mode(struct ata_device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ehc->i.flags |= ATA_EHI_POST_SETMODE;
|
||||
rc = ata_dev_revalidate(dev, 0);
|
||||
ehc->i.flags &= ~ATA_EHI_POST_SETMODE;
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -2323,11 +2550,14 @@ static inline void ata_tf_to_host(struct ata_port *ap,
|
|||
* Sleep until ATA Status register bit BSY clears,
|
||||
* or a timeout occurs.
|
||||
*
|
||||
* LOCKING: None.
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
|
||||
unsigned int ata_busy_sleep (struct ata_port *ap,
|
||||
unsigned long tmout_pat, unsigned long tmout)
|
||||
int ata_busy_sleep(struct ata_port *ap,
|
||||
unsigned long tmout_pat, unsigned long tmout)
|
||||
{
|
||||
unsigned long timer_start, timeout;
|
||||
u8 status;
|
||||
|
|
@ -2335,27 +2565,32 @@ unsigned int ata_busy_sleep (struct ata_port *ap,
|
|||
status = ata_busy_wait(ap, ATA_BUSY, 300);
|
||||
timer_start = jiffies;
|
||||
timeout = timer_start + tmout_pat;
|
||||
while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
|
||||
while (status != 0xff && (status & ATA_BUSY) &&
|
||||
time_before(jiffies, timeout)) {
|
||||
msleep(50);
|
||||
status = ata_busy_wait(ap, ATA_BUSY, 3);
|
||||
}
|
||||
|
||||
if (status & ATA_BUSY)
|
||||
if (status != 0xff && (status & ATA_BUSY))
|
||||
ata_port_printk(ap, KERN_WARNING,
|
||||
"port is slow to respond, please be patient "
|
||||
"(Status 0x%x)\n", status);
|
||||
|
||||
timeout = timer_start + tmout;
|
||||
while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
|
||||
while (status != 0xff && (status & ATA_BUSY) &&
|
||||
time_before(jiffies, timeout)) {
|
||||
msleep(50);
|
||||
status = ata_chk_status(ap);
|
||||
}
|
||||
|
||||
if (status == 0xff)
|
||||
return -ENODEV;
|
||||
|
||||
if (status & ATA_BUSY) {
|
||||
ata_port_printk(ap, KERN_ERR, "port failed to respond "
|
||||
"(%lu secs, Status 0x%x)\n",
|
||||
tmout / HZ, status);
|
||||
return 1;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2446,10 +2681,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
|
|||
* the bus shows 0xFF because the odd clown forgets the D7
|
||||
* pulldown resistor.
|
||||
*/
|
||||
if (ata_check_status(ap) == 0xFF) {
|
||||
ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
|
||||
return AC_ERR_OTHER;
|
||||
}
|
||||
if (ata_check_status(ap) == 0xFF)
|
||||
return 0;
|
||||
|
||||
ata_bus_post_reset(ap, devmask);
|
||||
|
||||
|
|
@ -2775,9 +3008,9 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
|
|||
}
|
||||
|
||||
/**
|
||||
* sata_std_hardreset - reset host port via SATA phy reset
|
||||
* sata_port_hardreset - reset port via SATA phy reset
|
||||
* @ap: port to reset
|
||||
* @class: resulting class of attached device
|
||||
* @timing: timing parameters { interval, duratinon, timeout } in msec
|
||||
*
|
||||
* SATA phy-reset host port using DET bits of SControl register.
|
||||
*
|
||||
|
|
@ -2787,10 +3020,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
|
|||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||
int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
|
||||
{
|
||||
struct ata_eh_context *ehc = &ap->eh_context;
|
||||
const unsigned long *timing = sata_ehc_deb_timing(ehc);
|
||||
u32 scontrol;
|
||||
int rc;
|
||||
|
||||
|
|
@ -2803,24 +3034,24 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
|||
* and Sil3124.
|
||||
*/
|
||||
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
scontrol = (scontrol & 0x0f0) | 0x304;
|
||||
|
||||
if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
sata_set_spd(ap);
|
||||
}
|
||||
|
||||
/* issue phy wake/reset */
|
||||
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
scontrol = (scontrol & 0x0f0) | 0x301;
|
||||
|
||||
if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
|
||||
* 10.4.2 says at least 1 ms.
|
||||
|
|
@ -2828,7 +3059,40 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
|||
msleep(1);
|
||||
|
||||
/* bring phy back */
|
||||
sata_phy_resume(ap, timing);
|
||||
rc = sata_phy_resume(ap, timing);
|
||||
out:
|
||||
DPRINTK("EXIT, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_std_hardreset - reset host port via SATA phy reset
|
||||
* @ap: port to reset
|
||||
* @class: resulting class of attached device
|
||||
*
|
||||
* SATA phy-reset host port using DET bits of SControl register,
|
||||
* wait for !BSY and classify the attached device.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||
{
|
||||
const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
/* do hardreset */
|
||||
rc = sata_port_hardreset(ap, timing);
|
||||
if (rc) {
|
||||
ata_port_printk(ap, KERN_ERR,
|
||||
"COMRESET failed (errno=%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* TODO: phy layer with polling, timeouts, etc. */
|
||||
if (ata_port_offline(ap)) {
|
||||
|
|
@ -2967,7 +3231,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
|||
/**
|
||||
* ata_dev_revalidate - Revalidate ATA device
|
||||
* @dev: device to revalidate
|
||||
* @post_reset: is this revalidation after reset?
|
||||
* @readid_flags: read ID flags
|
||||
*
|
||||
* Re-read IDENTIFY page and make sure @dev is still attached to
|
||||
* the port.
|
||||
|
|
@ -2978,7 +3242,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
|||
* RETURNS:
|
||||
* 0 on success, negative errno otherwise
|
||||
*/
|
||||
int ata_dev_revalidate(struct ata_device *dev, int post_reset)
|
||||
int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
|
||||
{
|
||||
unsigned int class = dev->class;
|
||||
u16 *id = (void *)dev->ap->sector_buf;
|
||||
|
|
@ -2990,7 +3254,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
|
|||
}
|
||||
|
||||
/* read ID data */
|
||||
rc = ata_dev_read_id(dev, &class, post_reset, id);
|
||||
rc = ata_dev_read_id(dev, &class, readid_flags, id);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
|
|
@ -3003,7 +3267,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
|
|||
memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
|
||||
|
||||
/* configure device according to the new ID */
|
||||
rc = ata_dev_configure(dev, 0);
|
||||
rc = ata_dev_configure(dev);
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -3012,37 +3276,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static const char * const ata_dma_blacklist [] = {
|
||||
"WDC AC11000H", NULL,
|
||||
"WDC AC22100H", NULL,
|
||||
"WDC AC32500H", NULL,
|
||||
"WDC AC33100H", NULL,
|
||||
"WDC AC31600H", NULL,
|
||||
"WDC AC32100H", "24.09P07",
|
||||
"WDC AC23200L", "21.10N21",
|
||||
"Compaq CRD-8241B", NULL,
|
||||
"CRD-8400B", NULL,
|
||||
"CRD-8480B", NULL,
|
||||
"CRD-8482B", NULL,
|
||||
"CRD-84", NULL,
|
||||
"SanDisk SDP3B", NULL,
|
||||
"SanDisk SDP3B-64", NULL,
|
||||
"SANYO CD-ROM CRD", NULL,
|
||||
"HITACHI CDR-8", NULL,
|
||||
"HITACHI CDR-8335", NULL,
|
||||
"HITACHI CDR-8435", NULL,
|
||||
"Toshiba CD-ROM XM-6202B", NULL,
|
||||
"TOSHIBA CD-ROM XM-1702BC", NULL,
|
||||
"CD-532E-A", NULL,
|
||||
"E-IDE CD-ROM CR-840", NULL,
|
||||
"CD-ROM Drive/F5A", NULL,
|
||||
"WPI CDD-820", NULL,
|
||||
"SAMSUNG CD-ROM SC-148C", NULL,
|
||||
"SAMSUNG CD-ROM SC", NULL,
|
||||
"SanDisk SDP3B-64", NULL,
|
||||
"ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,
|
||||
"_NEC DV5800A", NULL,
|
||||
"SAMSUNG CD-ROM SN-124", "N001"
|
||||
struct ata_blacklist_entry {
|
||||
const char *model_num;
|
||||
const char *model_rev;
|
||||
unsigned long horkage;
|
||||
};
|
||||
|
||||
static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
/* Devices with DMA related problems under Linux */
|
||||
{ "WDC AC11000H", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC22100H", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC32500H", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC33100H", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC31600H", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC32100H", "24.09P07", ATA_HORKAGE_NODMA },
|
||||
{ "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA },
|
||||
{ "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CRD-8400B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CRD-8480B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CRD-8482B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CRD-84", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "HITACHI CDR-8335", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "HITACHI CDR-8435", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CD-532E-A", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "E-IDE CD-ROM CR-840",NULL, ATA_HORKAGE_NODMA },
|
||||
{ "CD-ROM Drive/F5A", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "WPI CDD-820", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SAMSUNG CD-ROM SC-148C", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
|
||||
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
|
||||
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
|
||||
|
||||
/* Devices we expect to fail diagnostics */
|
||||
|
||||
/* Devices where NCQ should be avoided */
|
||||
/* NCQ is slow */
|
||||
{ "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
|
||||
|
||||
/* Devices with NCQ limits */
|
||||
|
||||
/* End Marker */
|
||||
{ }
|
||||
};
|
||||
|
||||
static int ata_strim(char *s, size_t len)
|
||||
|
|
@ -3057,20 +3339,12 @@ static int ata_strim(char *s, size_t len)
|
|||
return len;
|
||||
}
|
||||
|
||||
static int ata_dma_blacklisted(const struct ata_device *dev)
|
||||
unsigned long ata_device_blacklisted(const struct ata_device *dev)
|
||||
{
|
||||
unsigned char model_num[40];
|
||||
unsigned char model_rev[16];
|
||||
unsigned int nlen, rlen;
|
||||
int i;
|
||||
|
||||
/* We don't support polling DMA.
|
||||
* DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
|
||||
* if the LLDD handles only interrupts in the HSM_ST_LAST state.
|
||||
*/
|
||||
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
|
||||
(dev->flags & ATA_DFLAG_CDB_INTR))
|
||||
return 1;
|
||||
const struct ata_blacklist_entry *ad = ata_device_blacklist;
|
||||
|
||||
ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
|
||||
sizeof(model_num));
|
||||
|
|
@ -3079,17 +3353,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
|
|||
nlen = ata_strim(model_num, sizeof(model_num));
|
||||
rlen = ata_strim(model_rev, sizeof(model_rev));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) {
|
||||
if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) {
|
||||
if (ata_dma_blacklist[i+1] == NULL)
|
||||
return 1;
|
||||
if (!strncmp(ata_dma_blacklist[i], model_rev, rlen))
|
||||
return 1;
|
||||
while (ad->model_num) {
|
||||
if (!strncmp(ad->model_num, model_num, nlen)) {
|
||||
if (ad->model_rev == NULL)
|
||||
return ad->horkage;
|
||||
if (!strncmp(ad->model_rev, model_rev, rlen))
|
||||
return ad->horkage;
|
||||
}
|
||||
ad++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ata_dma_blacklisted(const struct ata_device *dev)
|
||||
{
|
||||
/* We don't support polling DMA.
|
||||
* DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
|
||||
* if the LLDD handles only interrupts in the HSM_ST_LAST state.
|
||||
*/
|
||||
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
|
||||
(dev->flags & ATA_DFLAG_CDB_INTR))
|
||||
return 1;
|
||||
return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_xfermask - Compute supported xfermask of the given device
|
||||
* @dev: Device to compute xfermask for
|
||||
|
|
@ -3117,6 +3404,13 @@ static void ata_dev_xfermask(struct ata_device *dev)
|
|||
*/
|
||||
if (ap->cbl == ATA_CBL_PATA40)
|
||||
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
|
||||
/* Apply drive side cable rule. Unknown or 80 pin cables reported
|
||||
* host side are checked drive side as well. Cases where we know a
|
||||
* 40wire cable is used safely for 80 are not checked here.
|
||||
*/
|
||||
if (ata_drive_40wire(dev->id) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80))
|
||||
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
|
||||
|
||||
|
||||
xfer_mask &= ata_pack_xfermask(dev->pio_mask,
|
||||
dev->mwdma_mask, dev->udma_mask);
|
||||
|
|
@ -3234,8 +3528,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
|
|||
* LOCKING:
|
||||
* spin_lock_irqsave(host lock)
|
||||
*/
|
||||
|
||||
static void ata_sg_clean(struct ata_queued_cmd *qc)
|
||||
void ata_sg_clean(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct scatterlist *sg = qc->__sg;
|
||||
|
|
@ -3393,19 +3686,15 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
|
|||
|
||||
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
|
||||
qc->flags |= ATA_QCFLAG_SINGLE;
|
||||
|
||||
memset(&qc->sgent, 0, sizeof(qc->sgent));
|
||||
qc->__sg = &qc->sgent;
|
||||
qc->n_elem = 1;
|
||||
qc->orig_n_elem = 1;
|
||||
qc->buf_virt = buf;
|
||||
qc->nbytes = buflen;
|
||||
|
||||
sg = qc->__sg;
|
||||
sg_init_one(sg, buf, buflen);
|
||||
sg_init_one(&qc->sgent, buf, buflen);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4198,8 +4487,12 @@ fsm_start:
|
|||
/* device stops HSM for abort/error */
|
||||
qc->err_mask |= AC_ERR_DEV;
|
||||
else
|
||||
/* HSM violation. Let EH handle this */
|
||||
qc->err_mask |= AC_ERR_HSM;
|
||||
/* HSM violation. Let EH handle this.
|
||||
* Phantom devices also trigger this
|
||||
* condition. Mark hint.
|
||||
*/
|
||||
qc->err_mask |= AC_ERR_HSM |
|
||||
AC_ERR_NODEV_HINT;
|
||||
|
||||
ap->hsm_task_state = HSM_ST_ERR;
|
||||
goto fsm_start;
|
||||
|
|
@ -4439,6 +4732,14 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
|
|||
qc->complete_fn(qc);
|
||||
}
|
||||
|
||||
static void fill_result_tf(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
|
||||
ap->ops->tf_read(ap, &qc->result_tf);
|
||||
qc->result_tf.flags = qc->tf.flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_qc_complete - Complete an active ATA command
|
||||
* @qc: Command to complete
|
||||
|
|
@ -4476,7 +4777,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
|
|||
if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
|
||||
if (!ata_tag_internal(qc->tag)) {
|
||||
/* always fill result TF for failed qc */
|
||||
ap->ops->tf_read(ap, &qc->result_tf);
|
||||
fill_result_tf(qc);
|
||||
ata_qc_schedule_eh(qc);
|
||||
return;
|
||||
}
|
||||
|
|
@ -4484,7 +4785,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
|
|||
|
||||
/* read result TF if requested */
|
||||
if (qc->flags & ATA_QCFLAG_RESULT_TF)
|
||||
ap->ops->tf_read(ap, &qc->result_tf);
|
||||
fill_result_tf(qc);
|
||||
|
||||
__ata_qc_complete(qc);
|
||||
} else {
|
||||
|
|
@ -4493,7 +4794,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
|
|||
|
||||
/* read result TF if failed or requested */
|
||||
if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
|
||||
ap->ops->tf_read(ap, &qc->result_tf);
|
||||
fill_result_tf(qc);
|
||||
|
||||
__ata_qc_complete(qc);
|
||||
}
|
||||
|
|
@ -4673,6 +4974,14 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||
}
|
||||
}
|
||||
|
||||
/* Some controllers show flaky interrupt behavior after
|
||||
* setting xfer mode. Use polling instead.
|
||||
*/
|
||||
if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES &&
|
||||
qc->tf.feature == SETFEATURES_XFER) &&
|
||||
(ap->flags & ATA_FLAG_SETXFER_POLLING))
|
||||
qc->tf.flags |= ATA_TFLAG_POLLING;
|
||||
|
||||
/* select the device */
|
||||
ata_dev_select(ap, qc->dev->devno, 1, 0);
|
||||
|
||||
|
|
@ -4781,6 +5090,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||
inline unsigned int ata_host_intr (struct ata_port *ap,
|
||||
struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_eh_info *ehi = &ap->eh_info;
|
||||
u8 status, host_stat = 0;
|
||||
|
||||
VPRINTK("ata%u: protocol %d task_state %d\n",
|
||||
|
|
@ -4841,6 +5151,11 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
|
|||
ap->ops->irq_clear(ap);
|
||||
|
||||
ata_hsm_move(ap, qc, status, 0);
|
||||
|
||||
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
|
||||
qc->tf.protocol == ATA_PROT_ATAPI_DMA))
|
||||
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
|
||||
|
||||
return 1; /* irq handled */
|
||||
|
||||
idle_irq:
|
||||
|
|
@ -5047,7 +5362,7 @@ int ata_flush_cache(struct ata_device *dev)
|
|||
if (!ata_try_flush_cache(dev))
|
||||
return 0;
|
||||
|
||||
if (ata_id_has_flush_ext(dev->id))
|
||||
if (dev->flags & ATA_DFLAG_FLUSH_EXT)
|
||||
cmd = ATA_CMD_FLUSH_EXT;
|
||||
else
|
||||
cmd = ATA_CMD_FLUSH;
|
||||
|
|
@ -5519,9 +5834,8 @@ int ata_device_add(const struct ata_probe_ent *ent)
|
|||
ap->ioaddr.bmdma_addr,
|
||||
irq_line);
|
||||
|
||||
ata_chk_status(ap);
|
||||
host->ops->irq_clear(ap);
|
||||
ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
|
||||
/* freeze port before requesting IRQ */
|
||||
ata_eh_freeze_port(ap);
|
||||
}
|
||||
|
||||
/* obtain irq, that may be shared between channels */
|
||||
|
|
@ -6119,6 +6433,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset);
|
|||
EXPORT_SYMBOL_GPL(ata_bus_reset);
|
||||
EXPORT_SYMBOL_GPL(ata_std_prereset);
|
||||
EXPORT_SYMBOL_GPL(ata_std_softreset);
|
||||
EXPORT_SYMBOL_GPL(sata_port_hardreset);
|
||||
EXPORT_SYMBOL_GPL(sata_std_hardreset);
|
||||
EXPORT_SYMBOL_GPL(ata_std_postreset);
|
||||
EXPORT_SYMBOL_GPL(ata_dev_classify);
|
||||
|
|
@ -6145,6 +6460,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend);
|
|||
EXPORT_SYMBOL_GPL(ata_host_resume);
|
||||
EXPORT_SYMBOL_GPL(ata_id_string);
|
||||
EXPORT_SYMBOL_GPL(ata_id_c_string);
|
||||
EXPORT_SYMBOL_GPL(ata_device_blacklisted);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
|
||||
|
||||
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
|
||||
|
|
|
|||
|
|
@ -1136,19 +1136,21 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
|
|||
break;
|
||||
|
||||
case ATA_DEV_ATAPI:
|
||||
tmp = atapi_eh_request_sense(qc->dev,
|
||||
qc->scsicmd->sense_buffer);
|
||||
if (!tmp) {
|
||||
/* ATA_QCFLAG_SENSE_VALID is used to tell
|
||||
* atapi_qc_complete() that sense data is
|
||||
* already valid.
|
||||
*
|
||||
* TODO: interpret sense data and set
|
||||
* appropriate err_mask.
|
||||
*/
|
||||
qc->flags |= ATA_QCFLAG_SENSE_VALID;
|
||||
} else
|
||||
qc->err_mask |= tmp;
|
||||
if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
|
||||
tmp = atapi_eh_request_sense(qc->dev,
|
||||
qc->scsicmd->sense_buffer);
|
||||
if (!tmp) {
|
||||
/* ATA_QCFLAG_SENSE_VALID is used to
|
||||
* tell atapi_qc_complete() that sense
|
||||
* data is already valid.
|
||||
*
|
||||
* TODO: interpret sense data and set
|
||||
* appropriate err_mask.
|
||||
*/
|
||||
qc->flags |= ATA_QCFLAG_SENSE_VALID;
|
||||
} else
|
||||
qc->err_mask |= tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
|
||||
|
|
@ -1433,16 +1435,39 @@ static void ata_eh_report(struct ata_port *ap)
|
|||
}
|
||||
|
||||
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
|
||||
static const char *dma_str[] = {
|
||||
[DMA_BIDIRECTIONAL] = "bidi",
|
||||
[DMA_TO_DEVICE] = "out",
|
||||
[DMA_FROM_DEVICE] = "in",
|
||||
[DMA_NONE] = "",
|
||||
};
|
||||
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
|
||||
struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
|
||||
unsigned int nbytes;
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
|
||||
continue;
|
||||
|
||||
ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
|
||||
"Emask 0x%x stat 0x%x err 0x%x (%s)\n",
|
||||
qc->tag, qc->tf.command, qc->err_mask,
|
||||
qc->result_tf.command, qc->result_tf.feature,
|
||||
ata_err_string(qc->err_mask));
|
||||
nbytes = qc->nbytes;
|
||||
if (!nbytes)
|
||||
nbytes = qc->nsect << 9;
|
||||
|
||||
ata_dev_printk(qc->dev, KERN_ERR,
|
||||
"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
|
||||
"tag %d cdb 0x%x data %u %s\n "
|
||||
"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
|
||||
"Emask 0x%x (%s)\n",
|
||||
cmd->command, cmd->feature, cmd->nsect,
|
||||
cmd->lbal, cmd->lbam, cmd->lbah,
|
||||
cmd->hob_feature, cmd->hob_nsect,
|
||||
cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah,
|
||||
cmd->device, qc->tag, qc->cdb[0], nbytes,
|
||||
dma_str[qc->dma_dir],
|
||||
res->command, res->feature, res->nsect,
|
||||
res->lbal, res->lbam, res->lbah,
|
||||
res->hob_feature, res->hob_nsect,
|
||||
res->hob_lbal, res->hob_lbam, res->hob_lbah,
|
||||
res->device, qc->err_mask, ata_err_string(qc->err_mask));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1634,11 +1659,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
|
|||
DPRINTK("ENTER\n");
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
unsigned int action;
|
||||
unsigned int action, readid_flags = 0;
|
||||
|
||||
dev = &ap->device[i];
|
||||
action = ata_eh_dev_action(dev);
|
||||
|
||||
if (ehc->i.flags & ATA_EHI_DID_RESET)
|
||||
readid_flags |= ATA_READID_POSTRESET;
|
||||
|
||||
if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
|
||||
if (ata_port_offline(ap)) {
|
||||
rc = -EIO;
|
||||
|
|
@ -1646,13 +1674,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
|
|||
}
|
||||
|
||||
ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
|
||||
rc = ata_dev_revalidate(dev,
|
||||
ehc->i.flags & ATA_EHI_DID_RESET);
|
||||
rc = ata_dev_revalidate(dev, readid_flags);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
|
||||
|
||||
/* Configuration may have changed, reconfigure
|
||||
* transfer mode.
|
||||
*/
|
||||
ehc->i.flags |= ATA_EHI_SETMODE;
|
||||
|
||||
/* schedule the scsi_rescan_device() here */
|
||||
queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
|
||||
} else if (dev->class == ATA_DEV_UNKNOWN &&
|
||||
|
|
@ -1660,18 +1692,35 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
|
|||
ata_class_enabled(ehc->classes[dev->devno])) {
|
||||
dev->class = ehc->classes[dev->devno];
|
||||
|
||||
rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
|
||||
if (rc == 0)
|
||||
rc = ata_dev_configure(dev, 1);
|
||||
rc = ata_dev_read_id(dev, &dev->class, readid_flags,
|
||||
dev->id);
|
||||
if (rc == 0) {
|
||||
ehc->i.flags |= ATA_EHI_PRINTINFO;
|
||||
rc = ata_dev_configure(dev);
|
||||
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
|
||||
} else if (rc == -ENOENT) {
|
||||
/* IDENTIFY was issued to non-existent
|
||||
* device. No need to reset. Just
|
||||
* thaw and kill the device.
|
||||
*/
|
||||
ata_eh_thaw_port(ap);
|
||||
dev->class = ATA_DEV_UNKNOWN;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
dev->class = ATA_DEV_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
if (ata_dev_enabled(dev)) {
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
/* new device discovered, configure xfermode */
|
||||
ehc->i.flags |= ATA_EHI_SETMODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1987,13 +2036,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||
if (rc)
|
||||
goto dev_fail;
|
||||
|
||||
/* configure transfer mode if the port has been reset */
|
||||
if (ehc->i.flags & ATA_EHI_DID_RESET) {
|
||||
/* configure transfer mode if necessary */
|
||||
if (ehc->i.flags & ATA_EHI_SETMODE) {
|
||||
rc = ata_set_mode(ap, &dev);
|
||||
if (rc) {
|
||||
down_xfermask = 1;
|
||||
goto dev_fail;
|
||||
}
|
||||
ehc->i.flags &= ~ATA_EHI_SETMODE;
|
||||
}
|
||||
|
||||
/* suspend devices */
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
|
|||
}
|
||||
|
||||
/*
|
||||
* ata_gen_ata_desc_sense - Generate check condition sense block.
|
||||
* ata_gen_passthru_sense - Generate check condition sense block.
|
||||
* @qc: Command that completed.
|
||||
*
|
||||
* This function is specific to the ATA descriptor format sense
|
||||
|
|
@ -681,9 +681,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
|
|||
* block. Clear sense key, ASC & ASCQ if there is no error.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host lock)
|
||||
* None.
|
||||
*/
|
||||
void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
|
||||
static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||
struct ata_taskfile *tf = &qc->result_tf;
|
||||
|
|
@ -713,12 +713,9 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
|
|||
|
||||
desc[0] = 0x09;
|
||||
|
||||
/*
|
||||
* Set length of additional sense data.
|
||||
* Since we only populate descriptor 0, the total
|
||||
* length is the same (fixed) length as descriptor 0.
|
||||
*/
|
||||
desc[1] = sb[7] = 14;
|
||||
/* set length of additional sense data */
|
||||
sb[7] = 14;
|
||||
desc[1] = 12;
|
||||
|
||||
/*
|
||||
* Copy registers into sense buffer.
|
||||
|
|
@ -746,56 +743,56 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
|
|||
}
|
||||
|
||||
/**
|
||||
* ata_gen_fixed_sense - generate a SCSI fixed sense block
|
||||
* ata_gen_ata_sense - generate a SCSI fixed sense block
|
||||
* @qc: Command that we are erroring out
|
||||
*
|
||||
* Leverage ata_to_sense_error() to give us the codes. Fit our
|
||||
* LBA in here if there's room.
|
||||
* Generate sense block for a failed ATA command @qc. Descriptor
|
||||
* format is used to accomodate LBA48 block address.
|
||||
*
|
||||
* LOCKING:
|
||||
* inherited from caller
|
||||
* None.
|
||||
*/
|
||||
void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
|
||||
static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_device *dev = qc->dev;
|
||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||
struct ata_taskfile *tf = &qc->result_tf;
|
||||
unsigned char *sb = cmd->sense_buffer;
|
||||
unsigned char *desc = sb + 8;
|
||||
int verbose = qc->ap->ops->error_handler == NULL;
|
||||
u64 block;
|
||||
|
||||
memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
|
||||
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
|
||||
|
||||
/*
|
||||
* Use ata_to_sense_error() to map status register bits
|
||||
/* sense data is current and format is descriptor */
|
||||
sb[0] = 0x72;
|
||||
|
||||
/* Use ata_to_sense_error() to map status register bits
|
||||
* onto sense key, asc & ascq.
|
||||
*/
|
||||
if (qc->err_mask ||
|
||||
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
|
||||
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
||||
&sb[2], &sb[12], &sb[13], verbose);
|
||||
sb[2] &= 0x0f;
|
||||
&sb[1], &sb[2], &sb[3], verbose);
|
||||
sb[1] &= 0x0f;
|
||||
}
|
||||
|
||||
sb[0] = 0x70;
|
||||
sb[7] = 0x0a;
|
||||
block = ata_tf_read_block(&qc->result_tf, dev);
|
||||
|
||||
if (tf->flags & ATA_TFLAG_LBA48) {
|
||||
/* TODO: find solution for LBA48 descriptors */
|
||||
}
|
||||
/* information sense data descriptor */
|
||||
sb[7] = 12;
|
||||
desc[0] = 0x00;
|
||||
desc[1] = 10;
|
||||
|
||||
else if (tf->flags & ATA_TFLAG_LBA) {
|
||||
/* A small (28b) LBA will fit in the 32b info field */
|
||||
sb[0] |= 0x80; /* set valid bit */
|
||||
sb[3] = tf->device & 0x0f;
|
||||
sb[4] = tf->lbah;
|
||||
sb[5] = tf->lbam;
|
||||
sb[6] = tf->lbal;
|
||||
}
|
||||
|
||||
else {
|
||||
/* TODO: C/H/S */
|
||||
}
|
||||
desc[2] |= 0x80; /* valid */
|
||||
desc[6] = block >> 40;
|
||||
desc[7] = block >> 32;
|
||||
desc[8] = block >> 24;
|
||||
desc[9] = block >> 16;
|
||||
desc[10] = block >> 8;
|
||||
desc[11] = block;
|
||||
}
|
||||
|
||||
static void ata_scsi_sdev_config(struct scsi_device *sdev)
|
||||
|
|
@ -807,23 +804,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
|
|||
static void ata_scsi_dev_config(struct scsi_device *sdev,
|
||||
struct ata_device *dev)
|
||||
{
|
||||
unsigned int max_sectors;
|
||||
/* configure max sectors */
|
||||
blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
|
||||
|
||||
/* TODO: 2048 is an arbitrary number, not the
|
||||
* hardware maximum. This should be increased to
|
||||
* 65534 when Jens Axboe's patch for dynamically
|
||||
* determining max_sectors is merged.
|
||||
*/
|
||||
max_sectors = ATA_MAX_SECTORS;
|
||||
if (dev->flags & ATA_DFLAG_LBA48)
|
||||
max_sectors = ATA_MAX_SECTORS_LBA48;
|
||||
if (dev->max_sectors)
|
||||
max_sectors = dev->max_sectors;
|
||||
|
||||
blk_queue_max_sectors(sdev->request_queue, max_sectors);
|
||||
|
||||
/*
|
||||
* SATA DMA transfers must be multiples of 4 byte, so
|
||||
/* SATA DMA transfers must be multiples of 4 byte, so
|
||||
* we need to pad ATAPI transfers using an extra sg.
|
||||
* Decrement max hw segments accordingly.
|
||||
*/
|
||||
|
|
@ -1040,8 +1024,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs
|
|||
tf->flags |= ATA_TFLAG_DEVICE;
|
||||
tf->protocol = ATA_PROT_NODATA;
|
||||
|
||||
if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
|
||||
(ata_id_has_flush_ext(qc->dev->id)))
|
||||
if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT)
|
||||
tf->command = ATA_CMD_FLUSH_EXT;
|
||||
else
|
||||
tf->command = ATA_CMD_FLUSH;
|
||||
|
|
@ -1282,17 +1265,14 @@ nothing_to_do:
|
|||
|
||||
static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
|
||||
{
|
||||
struct ata_taskfile *tf = &qc->tf;
|
||||
struct ata_device *dev = qc->dev;
|
||||
unsigned int tf_flags = 0;
|
||||
u64 block;
|
||||
u32 n_block;
|
||||
|
||||
qc->flags |= ATA_QCFLAG_IO;
|
||||
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
|
||||
int rc;
|
||||
|
||||
if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
|
||||
scsicmd[0] == WRITE_16)
|
||||
tf->flags |= ATA_TFLAG_WRITE;
|
||||
tf_flags |= ATA_TFLAG_WRITE;
|
||||
|
||||
/* Calculate the SCSI LBA, transfer length and FUA. */
|
||||
switch (scsicmd[0]) {
|
||||
|
|
@ -1300,7 +1280,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
case WRITE_10:
|
||||
scsi_10_lba_len(scsicmd, &block, &n_block);
|
||||
if (unlikely(scsicmd[1] & (1 << 3)))
|
||||
tf->flags |= ATA_TFLAG_FUA;
|
||||
tf_flags |= ATA_TFLAG_FUA;
|
||||
break;
|
||||
case READ_6:
|
||||
case WRITE_6:
|
||||
|
|
@ -1316,7 +1296,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
case WRITE_16:
|
||||
scsi_16_lba_len(scsicmd, &block, &n_block);
|
||||
if (unlikely(scsicmd[1] & (1 << 3)))
|
||||
tf->flags |= ATA_TFLAG_FUA;
|
||||
tf_flags |= ATA_TFLAG_FUA;
|
||||
break;
|
||||
default:
|
||||
DPRINTK("no-byte command\n");
|
||||
|
|
@ -1334,106 +1314,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
*/
|
||||
goto nothing_to_do;
|
||||
|
||||
if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
|
||||
ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
|
||||
/* yay, NCQ */
|
||||
if (!lba_48_ok(block, n_block))
|
||||
goto out_of_range;
|
||||
qc->flags |= ATA_QCFLAG_IO;
|
||||
qc->nsect = n_block;
|
||||
|
||||
tf->protocol = ATA_PROT_NCQ;
|
||||
tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
|
||||
|
||||
if (tf->flags & ATA_TFLAG_WRITE)
|
||||
tf->command = ATA_CMD_FPDMA_WRITE;
|
||||
else
|
||||
tf->command = ATA_CMD_FPDMA_READ;
|
||||
|
||||
qc->nsect = n_block;
|
||||
|
||||
tf->nsect = qc->tag << 3;
|
||||
tf->hob_feature = (n_block >> 8) & 0xff;
|
||||
tf->feature = n_block & 0xff;
|
||||
|
||||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
tf->lbah = (block >> 16) & 0xff;
|
||||
tf->lbam = (block >> 8) & 0xff;
|
||||
tf->lbal = block & 0xff;
|
||||
|
||||
tf->device = 1 << 6;
|
||||
if (tf->flags & ATA_TFLAG_FUA)
|
||||
tf->device |= 1 << 7;
|
||||
} else if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
|
||||
if (lba_28_ok(block, n_block)) {
|
||||
/* use LBA28 */
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
} else if (lba_48_ok(block, n_block)) {
|
||||
if (!(dev->flags & ATA_DFLAG_LBA48))
|
||||
goto out_of_range;
|
||||
|
||||
/* use LBA48 */
|
||||
tf->flags |= ATA_TFLAG_LBA48;
|
||||
|
||||
tf->hob_nsect = (n_block >> 8) & 0xff;
|
||||
|
||||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
} else
|
||||
/* request too large even for LBA48 */
|
||||
goto out_of_range;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(qc) < 0))
|
||||
goto invalid_fld;
|
||||
|
||||
qc->nsect = n_block;
|
||||
tf->nsect = n_block & 0xff;
|
||||
|
||||
tf->lbah = (block >> 16) & 0xff;
|
||||
tf->lbam = (block >> 8) & 0xff;
|
||||
tf->lbal = block & 0xff;
|
||||
|
||||
tf->device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
u32 sect, head, cyl, track;
|
||||
|
||||
/* The request -may- be too large for CHS addressing. */
|
||||
if (!lba_28_ok(block, n_block))
|
||||
goto out_of_range;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(qc) < 0))
|
||||
goto invalid_fld;
|
||||
|
||||
/* Convert LBA to CHS */
|
||||
track = (u32)block / dev->sectors;
|
||||
cyl = track / dev->heads;
|
||||
head = track % dev->heads;
|
||||
sect = (u32)block % dev->sectors + 1;
|
||||
|
||||
DPRINTK("block %u track %u cyl %u head %u sect %u\n",
|
||||
(u32)block, track, cyl, head, sect);
|
||||
|
||||
/* Check whether the converted CHS can fit.
|
||||
Cylinder: 0-65535
|
||||
Head: 0-15
|
||||
Sector: 1-255*/
|
||||
if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
|
||||
goto out_of_range;
|
||||
|
||||
qc->nsect = n_block;
|
||||
tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
|
||||
tf->lbal = sect;
|
||||
tf->lbam = cyl;
|
||||
tf->lbah = cyl >> 8;
|
||||
tf->device |= head;
|
||||
}
|
||||
|
||||
return 0;
|
||||
rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
|
||||
qc->tag);
|
||||
if (likely(rc == 0))
|
||||
return 0;
|
||||
|
||||
if (rc == -ERANGE)
|
||||
goto out_of_range;
|
||||
/* treat all other errors as -EINVAL, fall through */
|
||||
invalid_fld:
|
||||
ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
|
||||
/* "Invalid field in cbd" */
|
||||
|
|
@ -1477,7 +1368,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
|||
*/
|
||||
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
|
||||
((cdb[2] & 0x20) || need_sense)) {
|
||||
ata_gen_ata_desc_sense(qc);
|
||||
ata_gen_passthru_sense(qc);
|
||||
} else {
|
||||
if (!need_sense) {
|
||||
cmd->result = SAM_STAT_GOOD;
|
||||
|
|
@ -1488,7 +1379,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
|||
* good for smaller LBA (and maybe CHS?)
|
||||
* devices.
|
||||
*/
|
||||
ata_gen_fixed_sense(qc);
|
||||
ata_gen_ata_sense(qc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1714,6 +1605,22 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
|
|||
args->done(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
|
||||
* @idx: byte index into SCSI response buffer
|
||||
* @val: value to set
|
||||
*
|
||||
* To be used by SCSI command simulator functions. This macros
|
||||
* expects two local variables, u8 *rbuf and unsigned int buflen,
|
||||
* are in scope.
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*/
|
||||
#define ATA_SCSI_RBUF_SET(idx, val) do { \
|
||||
if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* ata_scsiop_inq_std - Simulate INQUIRY command
|
||||
* @args: device IDENTIFY data / SCSI command of interest.
|
||||
|
|
@ -2173,67 +2080,42 @@ saving_not_supp:
|
|||
* Simulate READ CAPACITY commands.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host lock)
|
||||
* None.
|
||||
*/
|
||||
|
||||
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
|
||||
unsigned int buflen)
|
||||
{
|
||||
u64 n_sectors;
|
||||
u32 tmp;
|
||||
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
if (ata_id_has_lba(args->id)) {
|
||||
if (ata_id_has_lba48(args->id))
|
||||
n_sectors = ata_id_u64(args->id, 100);
|
||||
else
|
||||
n_sectors = ata_id_u32(args->id, 60);
|
||||
} else {
|
||||
/* CHS default translation */
|
||||
n_sectors = args->id[1] * args->id[3] * args->id[6];
|
||||
|
||||
if (ata_id_current_chs_valid(args->id))
|
||||
/* CHS current translation */
|
||||
n_sectors = ata_id_u32(args->id, 57);
|
||||
}
|
||||
|
||||
n_sectors--; /* ATA TotalUserSectors - 1 */
|
||||
|
||||
if (args->cmd->cmnd[0] == READ_CAPACITY) {
|
||||
if( n_sectors >= 0xffffffffULL )
|
||||
tmp = 0xffffffff ; /* Return max count on overflow */
|
||||
else
|
||||
tmp = n_sectors ;
|
||||
if (last_lba >= 0xffffffffULL)
|
||||
last_lba = 0xffffffff;
|
||||
|
||||
/* sector count, 32-bit */
|
||||
rbuf[0] = tmp >> (8 * 3);
|
||||
rbuf[1] = tmp >> (8 * 2);
|
||||
rbuf[2] = tmp >> (8 * 1);
|
||||
rbuf[3] = tmp;
|
||||
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3));
|
||||
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2));
|
||||
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1));
|
||||
ATA_SCSI_RBUF_SET(3, last_lba);
|
||||
|
||||
/* sector size */
|
||||
tmp = ATA_SECT_SIZE;
|
||||
rbuf[6] = tmp >> 8;
|
||||
rbuf[7] = tmp;
|
||||
|
||||
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
|
||||
ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
|
||||
} else {
|
||||
/* sector count, 64-bit */
|
||||
tmp = n_sectors >> (8 * 4);
|
||||
rbuf[2] = tmp >> (8 * 3);
|
||||
rbuf[3] = tmp >> (8 * 2);
|
||||
rbuf[4] = tmp >> (8 * 1);
|
||||
rbuf[5] = tmp;
|
||||
tmp = n_sectors;
|
||||
rbuf[6] = tmp >> (8 * 3);
|
||||
rbuf[7] = tmp >> (8 * 2);
|
||||
rbuf[8] = tmp >> (8 * 1);
|
||||
rbuf[9] = tmp;
|
||||
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
|
||||
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6));
|
||||
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5));
|
||||
ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4));
|
||||
ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3));
|
||||
ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2));
|
||||
ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1));
|
||||
ATA_SCSI_RBUF_SET(7, last_lba);
|
||||
|
||||
/* sector size */
|
||||
tmp = ATA_SECT_SIZE;
|
||||
rbuf[12] = tmp >> 8;
|
||||
rbuf[13] = tmp;
|
||||
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
|
||||
ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2319,7 +2201,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc)
|
|||
* a sense descriptors, since that's only
|
||||
* correct for ATA, not ATAPI
|
||||
*/
|
||||
ata_gen_ata_desc_sense(qc);
|
||||
ata_gen_passthru_sense(qc);
|
||||
}
|
||||
|
||||
qc->scsidone(qc->scsicmd);
|
||||
|
|
@ -2394,7 +2276,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
|
|||
* sense descriptors, since that's only
|
||||
* correct for ATA, not ATAPI
|
||||
*/
|
||||
ata_gen_ata_desc_sense(qc);
|
||||
ata_gen_passthru_sense(qc);
|
||||
}
|
||||
|
||||
/* SCSI EH automatically locks door if sdev->locked is
|
||||
|
|
@ -2427,7 +2309,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
|
|||
* a sense descriptors, since that's only
|
||||
* correct for ATA, not ATAPI
|
||||
*/
|
||||
ata_gen_ata_desc_sense(qc);
|
||||
ata_gen_passthru_sense(qc);
|
||||
} else {
|
||||
u8 *scsicmd = cmd->cmnd;
|
||||
|
||||
|
|
@ -3183,10 +3065,12 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
|
|||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
if (rc == 0) {
|
||||
ata_port_schedule_eh(ap);
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
ata_port_wait_eh(ap);
|
||||
} else
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -3207,15 +3091,27 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
|||
{
|
||||
struct ata_port *ap =
|
||||
container_of(work, struct ata_port, scsi_rescan_task);
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
dev = &ap->device[i];
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
if (ata_dev_enabled(dev) && dev->sdev)
|
||||
scsi_rescan_device(&(dev->sdev->sdev_gendev));
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
struct ata_device *dev = &ap->device[i];
|
||||
struct scsi_device *sdev = dev->sdev;
|
||||
|
||||
if (!ata_dev_enabled(dev) || !sdev)
|
||||
continue;
|
||||
if (scsi_device_get(sdev))
|
||||
continue;
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
scsi_rescan_device(&(sdev->sdev_gendev));
|
||||
scsi_device_put(sdev);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,6 +38,35 @@
|
|||
|
||||
#include "libata.h"
|
||||
|
||||
/**
|
||||
* ata_irq_on - Enable interrupts on a port.
|
||||
* @ap: Port on which interrupts are enabled.
|
||||
*
|
||||
* Enable interrupts on a legacy IDE device using MMIO or PIO,
|
||||
* wait for idle, clear any pending interrupts.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
u8 ata_irq_on(struct ata_port *ap)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||
u8 tmp;
|
||||
|
||||
ap->ctl &= ~ATA_NIEN;
|
||||
ap->last_ctl = ap->ctl;
|
||||
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
|
||||
else
|
||||
outb(ap->ctl, ioaddr->ctl_addr);
|
||||
tmp = ata_wait_idle(ap);
|
||||
|
||||
ap->ops->irq_clear(ap);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_tf_load_pio - send taskfile registers to host controller
|
||||
* @ap: Port to which output is sent
|
||||
|
|
@ -671,6 +700,14 @@ void ata_bmdma_freeze(struct ata_port *ap)
|
|||
writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
|
||||
else
|
||||
outb(ap->ctl, ioaddr->ctl_addr);
|
||||
|
||||
/* Under certain circumstances, some controllers raise IRQ on
|
||||
* ATA_NIEN manipulation. Also, many controllers fail to mask
|
||||
* previously pending IRQ on ATA_NIEN assertion. Clear it.
|
||||
*/
|
||||
ata_chk_status(ap);
|
||||
|
||||
ap->ops->irq_clear(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -714,7 +751,6 @@ void ata_bmdma_drive_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)
|
||||
{
|
||||
struct ata_eh_context *ehc = &ap->eh_context;
|
||||
struct ata_queued_cmd *qc;
|
||||
unsigned long flags;
|
||||
int thaw = 0;
|
||||
|
|
@ -732,9 +768,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||
qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
|
||||
u8 host_stat;
|
||||
|
||||
host_stat = ata_bmdma_status(ap);
|
||||
|
||||
ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
|
||||
host_stat = ap->ops->bmdma_status(ap);
|
||||
|
||||
/* BMDMA controllers indicate host bus error by
|
||||
* setting DMA_ERR bit and timing out. As it wasn't
|
||||
|
|
@ -877,6 +911,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
|
|||
return NULL;
|
||||
|
||||
probe_ent->n_ports = 2;
|
||||
probe_ent->irq_flags = IRQF_SHARED;
|
||||
|
||||
if (port_mask & ATA_PORT_PRIMARY) {
|
||||
probe_ent->irq = ATA_PRIMARY_IRQ;
|
||||
|
|
|
|||
|
|
@ -39,26 +39,39 @@ struct ata_scsi_args {
|
|||
};
|
||||
|
||||
/* libata-core.c */
|
||||
enum {
|
||||
/* flags for ata_dev_read_id() */
|
||||
ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */
|
||||
};
|
||||
|
||||
extern struct workqueue_struct *ata_aux_wq;
|
||||
extern int atapi_enabled;
|
||||
extern int atapi_dmadir;
|
||||
extern int libata_fua;
|
||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
||||
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
|
||||
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||
u64 block, u32 n_block, unsigned int tf_flags,
|
||||
unsigned int tag);
|
||||
extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
|
||||
extern void ata_dev_disable(struct ata_device *dev);
|
||||
extern void ata_port_flush_task(struct ata_port *ap);
|
||||
extern unsigned ata_exec_internal(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, void *buf, unsigned int buflen);
|
||||
extern unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, struct scatterlist *sg,
|
||||
unsigned int n_elem);
|
||||
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,
|
||||
int post_reset, u16 *id);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
|
||||
extern int ata_dev_configure(struct ata_device *dev, int print_info);
|
||||
unsigned int flags, u16 *id);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags);
|
||||
extern int ata_dev_configure(struct ata_device *dev);
|
||||
extern int sata_down_spd_limit(struct ata_port *ap);
|
||||
extern int sata_set_spd_needed(struct ata_port *ap);
|
||||
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
|
||||
extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
|
||||
extern void ata_sg_clean(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_complete(struct ata_queued_cmd *qc);
|
||||
|
|
@ -120,4 +133,7 @@ extern void ata_scsi_error(struct Scsi_Host *host);
|
|||
extern void ata_port_wait_eh(struct ata_port *ap);
|
||||
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
|
||||
|
||||
/* libata-sff.c */
|
||||
extern u8 ata_irq_on(struct ata_port *ap);
|
||||
|
||||
#endif /* __LIBATA_H__ */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <linux/dmi.h>
|
||||
|
||||
#define DRV_NAME "pata_ali"
|
||||
#define DRV_VERSION "0.6.6"
|
||||
#define DRV_VERSION "0.7.2"
|
||||
|
||||
/*
|
||||
* Cable special cases
|
||||
|
|
@ -78,7 +78,7 @@ static int ali_c2_cable_detect(struct ata_port *ap)
|
|||
implement the detect logic */
|
||||
|
||||
if (ali_cable_override(pdev))
|
||||
return ATA_CBL_PATA80;
|
||||
return ATA_CBL_PATA40_SHORT;
|
||||
|
||||
/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
|
||||
Bit set for 40 pin */
|
||||
|
|
@ -337,9 +337,6 @@ static struct scsi_host_template ali_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
/* Keep LBA28 counts so large I/O's don't turn LBA48 and PIO
|
||||
with older controllers. Not locked so will grow on C5 or later */
|
||||
.max_sectors = 255,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -348,6 +345,8 @@ static struct scsi_host_template ali_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -497,6 +496,69 @@ static struct ata_port_operations ali_c5_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ali_init_chipset - chip setup function
|
||||
* @pdev: PCI device of ATA controller
|
||||
*
|
||||
* Perform the setup on the device that must be done both at boot
|
||||
* and at resume time.
|
||||
*/
|
||||
|
||||
static void ali_init_chipset(struct pci_dev *pdev)
|
||||
{
|
||||
u8 rev, tmp;
|
||||
struct pci_dev *north, *isa_bridge;
|
||||
|
||||
pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
|
||||
|
||||
/*
|
||||
* The chipset revision selects the driver operations and
|
||||
* mode data.
|
||||
*/
|
||||
|
||||
if (rev >= 0x20 && rev < 0xC2) {
|
||||
/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
|
||||
pci_read_config_byte(pdev, 0x4B, &tmp);
|
||||
/* Clear CD-ROM DMA write bit */
|
||||
tmp &= 0x7F;
|
||||
pci_write_config_byte(pdev, 0x4B, tmp);
|
||||
} else if (rev >= 0xC2) {
|
||||
/* Enable cable detection logic */
|
||||
pci_read_config_byte(pdev, 0x4B, &tmp);
|
||||
pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
|
||||
}
|
||||
north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
||||
|
||||
if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) {
|
||||
/* Configure the ALi bridge logic. For non ALi rely on BIOS.
|
||||
Set the south bridge enable bit */
|
||||
pci_read_config_byte(isa_bridge, 0x79, &tmp);
|
||||
if (rev == 0xC2)
|
||||
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
|
||||
else if (rev > 0xC2 && rev < 0xC5)
|
||||
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
|
||||
}
|
||||
if (rev >= 0x20) {
|
||||
/*
|
||||
* CD_ROM DMA on (0x53 bit 0). Enable this even if we want
|
||||
* to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
|
||||
* via 0x54/55.
|
||||
*/
|
||||
pci_read_config_byte(pdev, 0x53, &tmp);
|
||||
if (rev <= 0x20)
|
||||
tmp &= ~0x02;
|
||||
if (rev >= 0xc7)
|
||||
tmp |= 0x03;
|
||||
else
|
||||
tmp |= 0x01; /* CD_ROM enable for DMA */
|
||||
pci_write_config_byte(pdev, 0x53, tmp);
|
||||
}
|
||||
pci_dev_put(isa_bridge);
|
||||
pci_dev_put(north);
|
||||
ata_pci_clear_simplex(pdev);
|
||||
}
|
||||
/**
|
||||
* ali_init_one - discovery callback
|
||||
* @pdev: PCI device ID
|
||||
|
|
@ -570,7 +632,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
|
||||
static struct ata_port_info *port_info[2];
|
||||
u8 rev, tmp;
|
||||
struct pci_dev *north, *isa_bridge;
|
||||
struct pci_dev *isa_bridge;
|
||||
|
||||
pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
|
||||
|
||||
|
|
@ -582,11 +644,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
if (rev < 0x20) {
|
||||
port_info[0] = port_info[1] = &info_early;
|
||||
} else if (rev < 0xC2) {
|
||||
/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
|
||||
pci_read_config_byte(pdev, 0x4B, &tmp);
|
||||
/* Clear CD-ROM DMA write bit */
|
||||
tmp &= 0x7F;
|
||||
pci_write_config_byte(pdev, 0x4B, tmp);
|
||||
port_info[0] = port_info[1] = &info_20;
|
||||
} else if (rev == 0xC2) {
|
||||
port_info[0] = port_info[1] = &info_c2;
|
||||
|
|
@ -597,54 +654,25 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
} else
|
||||
port_info[0] = port_info[1] = &info_c5;
|
||||
|
||||
if (rev >= 0xC2) {
|
||||
/* Enable cable detection logic */
|
||||
pci_read_config_byte(pdev, 0x4B, &tmp);
|
||||
pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
|
||||
}
|
||||
|
||||
north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0));
|
||||
ali_init_chipset(pdev);
|
||||
|
||||
isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
||||
|
||||
if (north && north->vendor == PCI_VENDOR_ID_AL) {
|
||||
/* Configure the ALi bridge logic. For non ALi rely on BIOS.
|
||||
Set the south bridge enable bit */
|
||||
pci_read_config_byte(isa_bridge, 0x79, &tmp);
|
||||
if (rev == 0xC2)
|
||||
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
|
||||
else if (rev > 0xC2)
|
||||
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
|
||||
if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
|
||||
/* Are we paired with a UDMA capable chip */
|
||||
pci_read_config_byte(isa_bridge, 0x5E, &tmp);
|
||||
if ((tmp & 0x1E) == 0x12)
|
||||
port_info[0] = port_info[1] = &info_20_udma;
|
||||
pci_dev_put(isa_bridge);
|
||||
}
|
||||
|
||||
if (rev >= 0x20) {
|
||||
if (rev < 0xC2) {
|
||||
/* Are we paired with a UDMA capable chip */
|
||||
pci_read_config_byte(isa_bridge, 0x5E, &tmp);
|
||||
if ((tmp & 0x1E) == 0x12)
|
||||
port_info[0] = port_info[1] = &info_20_udma;
|
||||
}
|
||||
/*
|
||||
* CD_ROM DMA on (0x53 bit 0). Enable this even if we want
|
||||
* to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
|
||||
* via 0x54/55.
|
||||
*/
|
||||
pci_read_config_byte(pdev, 0x53, &tmp);
|
||||
if (rev <= 0x20)
|
||||
tmp &= ~0x02;
|
||||
if (rev >= 0xc7)
|
||||
tmp |= 0x03;
|
||||
else
|
||||
tmp |= 0x01; /* CD_ROM enable for DMA */
|
||||
pci_write_config_byte(pdev, 0x53, tmp);
|
||||
}
|
||||
|
||||
pci_dev_put(isa_bridge);
|
||||
pci_dev_put(north);
|
||||
|
||||
ata_pci_clear_simplex(pdev);
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int ali_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
ali_init_chipset(pdev);
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id ali[] = {
|
||||
{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
|
||||
{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), },
|
||||
|
|
@ -656,7 +684,9 @@ static struct pci_driver ali_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = ali,
|
||||
.probe = ali_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ali_reinit_one,
|
||||
};
|
||||
|
||||
static int __init ali_init(void)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_amd"
|
||||
#define DRV_VERSION "0.2.4"
|
||||
#define DRV_VERSION "0.2.7"
|
||||
|
||||
/**
|
||||
* timing_setup - shared timing computation and load
|
||||
|
|
@ -326,7 +326,6 @@ static struct scsi_host_template amd_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -335,6 +334,8 @@ static struct scsi_host_template amd_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations amd33_port_ops = {
|
||||
|
|
@ -662,6 +663,23 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int amd_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD) {
|
||||
u8 fifo;
|
||||
pci_read_config_byte(pdev, 0x41, &fifo);
|
||||
if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
|
||||
/* FIFO is broken */
|
||||
pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
|
||||
else
|
||||
pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
|
||||
if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
|
||||
pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
|
||||
ata_pci_clear_simplex(pdev);
|
||||
}
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id amd[] = {
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 },
|
||||
|
|
@ -689,7 +707,9 @@ static struct pci_driver amd_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = amd,
|
||||
.probe = amd_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = amd_reinit_one,
|
||||
};
|
||||
|
||||
static int __init amd_init(void)
|
||||
|
|
|
|||
|
|
@ -307,7 +307,6 @@ static struct scsi_host_template artop_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_atiixp"
|
||||
#define DRV_VERSION "0.4.3"
|
||||
#define DRV_VERSION "0.4.4"
|
||||
|
||||
enum {
|
||||
ATIIXP_IDE_PIO_TIMING = 0x40,
|
||||
|
|
@ -209,7 +209,6 @@ static struct scsi_host_template atiixp_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -218,6 +217,8 @@ static struct scsi_host_template atiixp_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations atiixp_port_ops = {
|
||||
|
|
@ -281,7 +282,9 @@ static struct pci_driver atiixp_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = atiixp,
|
||||
.probe = atiixp_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.resume = ata_pci_device_resume,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
};
|
||||
|
||||
static int __init atiixp_init(void)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_cmd64x"
|
||||
#define DRV_VERSION "0.2.1"
|
||||
#define DRV_VERSION "0.2.2"
|
||||
|
||||
/*
|
||||
* CMD64x specific registers definition.
|
||||
|
|
@ -268,7 +268,6 @@ static struct scsi_host_template cmd64x_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -277,6 +276,8 @@ static struct scsi_host_template cmd64x_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cmd64x_port_ops = {
|
||||
|
|
@ -469,6 +470,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int cmd64x_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
u8 mrdmode;
|
||||
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
|
||||
pci_read_config_byte(pdev, MRDMODE, &mrdmode);
|
||||
mrdmode &= ~ 0x30; /* IRQ set up */
|
||||
mrdmode |= 0x02; /* Memory read line enable */
|
||||
pci_write_config_byte(pdev, MRDMODE, mrdmode);
|
||||
#ifdef CONFIG_PPC
|
||||
pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
|
||||
#endif
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id cmd64x[] = {
|
||||
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
|
||||
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
|
||||
|
|
@ -482,7 +497,9 @@ static struct pci_driver cmd64x_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = cmd64x,
|
||||
.probe = cmd64x_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = cmd64x_reinit_one,
|
||||
};
|
||||
|
||||
static int __init cmd64x_init(void)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_cs5520"
|
||||
#define DRV_VERSION "0.6.2"
|
||||
#define DRV_VERSION "0.6.3"
|
||||
|
||||
struct pio_clocks
|
||||
{
|
||||
|
|
@ -159,7 +159,6 @@ static struct scsi_host_template cs5520_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -168,6 +167,8 @@ static struct scsi_host_template cs5520_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cs5520_port_ops = {
|
||||
|
|
@ -297,6 +298,22 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev)
|
|||
dev_set_drvdata(dev, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5520_reinit_one - device resume
|
||||
* @pdev: PCI device
|
||||
*
|
||||
* Do any reconfiguration work needed by a resume from RAM. We need
|
||||
* to restore DMA mode support on BIOSen which disabled it
|
||||
*/
|
||||
|
||||
static int cs5520_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
u8 pcicfg;
|
||||
pci_read_config_byte(pdev, 0x60, &pcicfg);
|
||||
if ((pcicfg & 0x40) == 0)
|
||||
pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
/* For now keep DMA off. We can set it for all but A rev CS5510 once the
|
||||
core ATA code can handle it */
|
||||
|
||||
|
|
@ -311,7 +328,9 @@ static struct pci_driver cs5520_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = pata_cs5520,
|
||||
.probe = cs5520_init_one,
|
||||
.remove = cs5520_remove_one
|
||||
.remove = cs5520_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = cs5520_reinit_one,
|
||||
};
|
||||
|
||||
static int __init cs5520_init(void)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include <linux/dmi.h>
|
||||
|
||||
#define DRV_NAME "pata_cs5530"
|
||||
#define DRV_VERSION "0.6"
|
||||
#define DRV_VERSION "0.7.1"
|
||||
|
||||
/**
|
||||
* cs5530_set_piomode - PIO setup
|
||||
|
|
@ -173,7 +173,6 @@ static struct scsi_host_template cs5530_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -182,6 +181,8 @@ static struct scsi_host_template cs5530_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cs5530_port_ops = {
|
||||
|
|
@ -239,38 +240,18 @@ static int cs5530_is_palmax(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cs5530_init_one - Initialise a CS5530
|
||||
* @dev: PCI device
|
||||
* @id: Entry in match table
|
||||
* cs5530_init_chip - Chipset init
|
||||
*
|
||||
* Install a driver for the newly found CS5530 companion chip. Most of
|
||||
* this is just housekeeping. We have to set the chip up correctly and
|
||||
* turn off various bits of emulation magic.
|
||||
* Perform the chip initialisation work that is shared between both
|
||||
* setup and resume paths
|
||||
*/
|
||||
|
||||
static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
static int cs5530_init_chip(void)
|
||||
{
|
||||
int compiler_warning_pointless_fix;
|
||||
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
|
||||
static struct ata_port_info info = {
|
||||
.sht = &cs5530_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x07,
|
||||
.port_ops = &cs5530_port_ops
|
||||
};
|
||||
/* The docking connector doesn't do UDMA, and it seems not MWDMA */
|
||||
static struct ata_port_info info_palmax_secondary = {
|
||||
.sht = &cs5530_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.port_ops = &cs5530_port_ops
|
||||
};
|
||||
static struct ata_port_info *port_info[2] = { &info, &info };
|
||||
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL;
|
||||
|
||||
dev = NULL;
|
||||
while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
|
||||
switch (dev->device) {
|
||||
case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
|
||||
|
|
@ -291,7 +272,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
}
|
||||
|
||||
pci_set_master(cs5530_0);
|
||||
compiler_warning_pointless_fix = pci_set_mwi(cs5530_0);
|
||||
pci_set_mwi(cs5530_0);
|
||||
|
||||
/*
|
||||
* Set PCI CacheLineSize to 16-bytes:
|
||||
|
|
@ -339,13 +320,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
|
||||
pci_dev_put(master_0);
|
||||
pci_dev_put(cs5530_0);
|
||||
|
||||
if (cs5530_is_palmax())
|
||||
port_info[1] = &info_palmax_secondary;
|
||||
|
||||
/* Now kick off ATA set up */
|
||||
return ata_pci_init_one(dev, port_info, 2);
|
||||
|
||||
return 0;
|
||||
fail_put:
|
||||
if (master_0)
|
||||
pci_dev_put(master_0);
|
||||
|
|
@ -354,6 +329,53 @@ fail_put:
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5530_init_one - Initialise a CS5530
|
||||
* @dev: PCI device
|
||||
* @id: Entry in match table
|
||||
*
|
||||
* Install a driver for the newly found CS5530 companion chip. Most of
|
||||
* this is just housekeeping. We have to set the chip up correctly and
|
||||
* turn off various bits of emulation magic.
|
||||
*/
|
||||
|
||||
static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
static struct ata_port_info info = {
|
||||
.sht = &cs5530_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x07,
|
||||
.port_ops = &cs5530_port_ops
|
||||
};
|
||||
/* The docking connector doesn't do UDMA, and it seems not MWDMA */
|
||||
static struct ata_port_info info_palmax_secondary = {
|
||||
.sht = &cs5530_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.port_ops = &cs5530_port_ops
|
||||
};
|
||||
static struct ata_port_info *port_info[2] = { &info, &info };
|
||||
|
||||
/* Chip initialisation */
|
||||
if (cs5530_init_chip())
|
||||
return -ENODEV;
|
||||
|
||||
if (cs5530_is_palmax())
|
||||
port_info[1] = &info_palmax_secondary;
|
||||
|
||||
/* Now kick off ATA set up */
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int cs5530_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
/* If we fail on resume we are doomed */
|
||||
BUG_ON(cs5530_init_chip());
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id cs5530[] = {
|
||||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
|
||||
|
||||
|
|
@ -364,7 +386,9 @@ static struct pci_driver cs5530_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = cs5530,
|
||||
.probe = cs5530_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = cs5530_reinit_one,
|
||||
};
|
||||
|
||||
static int __init cs5530_init(void)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#include <asm/msr.h>
|
||||
|
||||
#define DRV_NAME "cs5535"
|
||||
#define DRV_VERSION "0.2.10"
|
||||
#define DRV_VERSION "0.2.11"
|
||||
|
||||
/*
|
||||
* The Geode (Aka Athlon GX now) uses an internal MSR based
|
||||
|
|
@ -177,7 +177,6 @@ static struct scsi_host_template cs5535_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -186,6 +185,8 @@ static struct scsi_host_template cs5535_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cs5535_port_ops = {
|
||||
|
|
@ -268,7 +269,9 @@ static struct pci_driver cs5535_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = cs5535,
|
||||
.probe = cs5535_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init cs5535_init(void)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_cypress"
|
||||
#define DRV_VERSION "0.1.2"
|
||||
#define DRV_VERSION "0.1.4"
|
||||
|
||||
/* here are the offset definitions for the registers */
|
||||
|
||||
|
|
@ -128,7 +128,6 @@ static struct scsi_host_template cy82c693_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -137,6 +136,8 @@ static struct scsi_host_template cy82c693_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cy82c693_port_ops = {
|
||||
|
|
@ -204,7 +205,9 @@ static struct pci_driver cy82c693_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = cy82c693,
|
||||
.probe = cy82c693_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init cy82c693_init(void)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_efar"
|
||||
#define DRV_VERSION "0.4.2"
|
||||
#define DRV_VERSION "0.4.3"
|
||||
|
||||
/**
|
||||
* efar_pre_reset - check for 40/80 pin
|
||||
|
|
@ -226,7 +226,6 @@ static struct scsi_host_template efar_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -235,6 +234,8 @@ static struct scsi_host_template efar_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations efar_ops = {
|
||||
|
|
@ -316,6 +317,8 @@ static struct pci_driver efar_pci_driver = {
|
|||
.id_table = efar_pci_tbl,
|
||||
.probe = efar_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init efar_init(void)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt366"
|
||||
#define DRV_VERSION "0.5"
|
||||
#define DRV_VERSION "0.5.3"
|
||||
|
||||
struct hpt_clock {
|
||||
u8 xfer_speed;
|
||||
|
|
@ -222,9 +222,17 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
|
|||
|
||||
static int hpt36x_pre_reset(struct ata_port *ap)
|
||||
{
|
||||
static const struct pci_bits hpt36x_enable_bits[] = {
|
||||
{ 0x50, 1, 0x04, 0x04 },
|
||||
{ 0x54, 1, 0x04, 0x04 }
|
||||
};
|
||||
|
||||
u8 ata66;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
|
||||
if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
|
||||
return -ENOENT;
|
||||
|
||||
pci_read_config_byte(pdev, 0x5A, &ata66);
|
||||
if (ata66 & (1 << ap->port_no))
|
||||
ap->cbl = ATA_CBL_PATA40;
|
||||
|
|
@ -322,7 +330,6 @@ static struct scsi_host_template hpt36x_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -331,6 +338,8 @@ static struct scsi_host_template hpt36x_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -372,6 +381,27 @@ static struct ata_port_operations hpt366_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
/**
|
||||
* hpt36x_init_chipset - common chip setup
|
||||
* @dev: PCI device
|
||||
*
|
||||
* Perform the chip setup work that must be done at both init and
|
||||
* resume time
|
||||
*/
|
||||
|
||||
static void hpt36x_init_chipset(struct pci_dev *dev)
|
||||
{
|
||||
u8 drive_fast;
|
||||
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
|
||||
pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
|
||||
pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
|
||||
|
||||
pci_read_config_byte(dev, 0x51, &drive_fast);
|
||||
if (drive_fast & 0x80)
|
||||
pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
|
||||
}
|
||||
|
||||
/**
|
||||
* hpt36x_init_one - Initialise an HPT366/368
|
||||
* @dev: PCI device
|
||||
|
|
@ -407,7 +437,6 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
|
||||
u32 class_rev;
|
||||
u32 reg1;
|
||||
u8 drive_fast;
|
||||
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xFF;
|
||||
|
|
@ -417,14 +446,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
if (class_rev > 2)
|
||||
return -ENODEV;
|
||||
|
||||
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
|
||||
pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
|
||||
pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
|
||||
|
||||
pci_read_config_byte(dev, 0x51, &drive_fast);
|
||||
if (drive_fast & 0x80)
|
||||
pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
|
||||
hpt36x_init_chipset(dev);
|
||||
|
||||
pci_read_config_dword(dev, 0x40, ®1);
|
||||
|
||||
|
|
@ -445,9 +467,15 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(dev, port_info, 2);
|
||||
}
|
||||
|
||||
static int hpt36x_reinit_one(struct pci_dev *dev)
|
||||
{
|
||||
hpt36x_init_chipset(dev);
|
||||
return ata_pci_device_resume(dev);
|
||||
}
|
||||
|
||||
|
||||
static const struct pci_device_id hpt36x[] = {
|
||||
{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
|
||||
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
@ -455,7 +483,9 @@ static struct pci_driver hpt36x_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = hpt36x,
|
||||
.probe = hpt36x_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = hpt36x_reinit_one,
|
||||
};
|
||||
|
||||
static int __init hpt36x_init(void)
|
||||
|
|
@ -463,13 +493,11 @@ static int __init hpt36x_init(void)
|
|||
return pci_register_driver(&hpt36x_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
static void __exit hpt36x_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&hpt36x_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -768,7 +768,6 @@ static struct scsi_host_template hpt37x_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -334,7 +334,6 @@ static struct scsi_host_template hpt3x2n_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt3x3"
|
||||
#define DRV_VERSION "0.4.1"
|
||||
#define DRV_VERSION "0.4.2"
|
||||
|
||||
static int hpt3x3_probe_init(struct ata_port *ap)
|
||||
{
|
||||
|
|
@ -111,7 +111,6 @@ static struct scsi_host_template hpt3x3_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -120,6 +119,8 @@ static struct scsi_host_template hpt3x3_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations hpt3x3_port_ops = {
|
||||
|
|
@ -157,6 +158,27 @@ static struct ata_port_operations hpt3x3_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
/**
|
||||
* hpt3x3_init_chipset - chip setup
|
||||
* @dev: PCI device
|
||||
*
|
||||
* Perform the setup required at boot and on resume.
|
||||
*/
|
||||
|
||||
static void hpt3x3_init_chipset(struct pci_dev *dev)
|
||||
{
|
||||
u16 cmd;
|
||||
/* Initialize the board */
|
||||
pci_write_config_word(dev, 0x80, 0x00);
|
||||
/* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
if (cmd & PCI_COMMAND_MEMORY)
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
|
||||
else
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hpt3x3_init_one - Initialise an HPT343/363
|
||||
* @dev: PCI device
|
||||
|
|
@ -178,21 +200,18 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
.port_ops = &hpt3x3_port_ops
|
||||
};
|
||||
static struct ata_port_info *port_info[2] = { &info, &info };
|
||||
u16 cmd;
|
||||
|
||||
/* Initialize the board */
|
||||
pci_write_config_word(dev, 0x80, 0x00);
|
||||
/* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
if (cmd & PCI_COMMAND_MEMORY)
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
|
||||
else
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
|
||||
|
||||
hpt3x3_init_chipset(dev);
|
||||
/* Now kick off ATA set up */
|
||||
return ata_pci_init_one(dev, port_info, 2);
|
||||
}
|
||||
|
||||
static int hpt3x3_reinit_one(struct pci_dev *dev)
|
||||
{
|
||||
hpt3x3_init_chipset(dev);
|
||||
return ata_pci_device_resume(dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id hpt3x3[] = {
|
||||
{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), },
|
||||
|
||||
|
|
@ -203,7 +222,9 @@ static struct pci_driver hpt3x3_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = hpt3x3,
|
||||
.probe = hpt3x3_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = hpt3x3_reinit_one,
|
||||
};
|
||||
|
||||
static int __init hpt3x3_init(void)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ static struct scsi_host_template isapnp_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
|
||||
#define DRV_NAME "pata_it821x"
|
||||
#define DRV_VERSION "0.3.2"
|
||||
#define DRV_VERSION "0.3.3"
|
||||
|
||||
struct it821x_dev
|
||||
{
|
||||
|
|
@ -666,9 +666,6 @@ static struct scsi_host_template it821x_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
/* 255 sectors to begin with. This is locked in smart mode but not
|
||||
in pass through */
|
||||
.max_sectors = 255,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -677,6 +674,8 @@ static struct scsi_host_template it821x_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations it821x_smart_port_ops = {
|
||||
|
|
@ -809,6 +808,14 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int it821x_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
/* Resume - turn raid back off if need be */
|
||||
if (it8212_noraid)
|
||||
it821x_disable_raid(pdev);
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id it821x[] = {
|
||||
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), },
|
||||
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), },
|
||||
|
|
@ -820,7 +827,9 @@ static struct pci_driver it821x_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = it821x,
|
||||
.probe = it821x_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = it821x_reinit_one,
|
||||
};
|
||||
|
||||
static int __init it821x_init(void)
|
||||
|
|
|
|||
271
drivers/ata/pata_ixp4xx_cf.c
Normal file
271
drivers/ata/pata_ixp4xx_cf.c
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* ixp4xx PATA/Compact Flash driver
|
||||
* Copyright (c) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* An ATA driver to handle a Compact Flash connected
|
||||
* to the ixp4xx expansion bus in TrueIDE mode. The CF
|
||||
* must have it chip selects connected to two CS lines
|
||||
* on the ixp4xx. The interrupt line is optional, if not
|
||||
* specified the driver will run in polling mode.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#define DRV_NAME "pata_ixp4xx_cf"
|
||||
#define DRV_VERSION "0.1.1"
|
||||
|
||||
static void ixp4xx_set_mode(struct ata_port *ap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
struct ata_device *dev = &ap->device[i];
|
||||
if (ata_dev_enabled(dev)) {
|
||||
dev->pio_mode = XFER_PIO_0;
|
||||
dev->xfer_mode = XFER_PIO_0;
|
||||
dev->xfer_shift = ATA_SHIFT_PIO;
|
||||
dev->flags |= ATA_DFLAG_PIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ixp4xx_phy_reset(struct ata_port *ap)
|
||||
{
|
||||
ap->cbl = ATA_CBL_PATA40;
|
||||
ata_port_probe(ap);
|
||||
ata_bus_reset(ap);
|
||||
}
|
||||
|
||||
static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
|
||||
unsigned int buflen, int write_data)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int words = buflen >> 1;
|
||||
u16 *buf16 = (u16 *) buf;
|
||||
struct ata_port *ap = adev->ap;
|
||||
void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
|
||||
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
|
||||
|
||||
/* set the expansion bus in 16bit mode and restore
|
||||
* 8 bit mode after the transaction.
|
||||
*/
|
||||
*data->cs0_cfg &= ~(0x01);
|
||||
udelay(100);
|
||||
|
||||
/* Transfer multiple of 2 bytes */
|
||||
if (write_data) {
|
||||
for (i = 0; i < words; i++)
|
||||
writew(buf16[i], mmio);
|
||||
} else {
|
||||
for (i = 0; i < words; i++)
|
||||
buf16[i] = readw(mmio);
|
||||
}
|
||||
|
||||
/* Transfer trailing 1 byte, if any. */
|
||||
if (unlikely(buflen & 0x01)) {
|
||||
u16 align_buf[1] = { 0 };
|
||||
unsigned char *trailing_buf = buf + buflen - 1;
|
||||
|
||||
if (write_data) {
|
||||
memcpy(align_buf, trailing_buf, 1);
|
||||
writew(align_buf[0], mmio);
|
||||
} else {
|
||||
align_buf[0] = readw(mmio);
|
||||
memcpy(trailing_buf, align_buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
*data->cs0_cfg |= 0x01;
|
||||
}
|
||||
|
||||
static void ixp4xx_irq_clear(struct ata_port *ap)
|
||||
{
|
||||
}
|
||||
|
||||
static void ixp4xx_host_stop (struct ata_host *host)
|
||||
{
|
||||
struct ixp4xx_pata_data *data = host->dev->platform_data;
|
||||
|
||||
iounmap(data->cs0);
|
||||
iounmap(data->cs1);
|
||||
}
|
||||
|
||||
static struct scsi_host_template ixp4xx_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 ixp4xx_port_ops = {
|
||||
.set_mode = ixp4xx_set_mode,
|
||||
.mode_filter = ata_pci_default_filter,
|
||||
|
||||
.port_disable = ata_port_disable,
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
.check_status = ata_check_status,
|
||||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.qc_prep = ata_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
.eng_timeout = ata_eng_timeout,
|
||||
.data_xfer = ixp4xx_mmio_data_xfer,
|
||||
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ixp4xx_irq_clear,
|
||||
|
||||
.port_start = ata_port_start,
|
||||
.port_stop = ata_port_stop,
|
||||
.host_stop = ixp4xx_host_stop,
|
||||
|
||||
.phy_reset = ixp4xx_phy_reset,
|
||||
};
|
||||
|
||||
static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
|
||||
struct ixp4xx_pata_data *data)
|
||||
{
|
||||
ioaddr->cmd_addr = (unsigned long) data->cs0;
|
||||
ioaddr->altstatus_addr = (unsigned long) data->cs1 + 0x06;
|
||||
ioaddr->ctl_addr = (unsigned long) data->cs1 + 0x06;
|
||||
|
||||
ata_std_ports(ioaddr);
|
||||
|
||||
#ifndef __ARMEB__
|
||||
|
||||
/* adjust the addresses to handle the address swizzling of the
|
||||
* ixp4xx in little endian mode.
|
||||
*/
|
||||
|
||||
ioaddr->data_addr ^= 0x02;
|
||||
ioaddr->cmd_addr ^= 0x03;
|
||||
ioaddr->altstatus_addr ^= 0x03;
|
||||
ioaddr->ctl_addr ^= 0x03;
|
||||
ioaddr->error_addr ^= 0x03;
|
||||
ioaddr->feature_addr ^= 0x03;
|
||||
ioaddr->nsect_addr ^= 0x03;
|
||||
ioaddr->lbal_addr ^= 0x03;
|
||||
ioaddr->lbam_addr ^= 0x03;
|
||||
ioaddr->lbah_addr ^= 0x03;
|
||||
ioaddr->device_addr ^= 0x03;
|
||||
ioaddr->status_addr ^= 0x03;
|
||||
ioaddr->command_addr ^= 0x03;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
unsigned int irq;
|
||||
struct resource *cs0, *cs1;
|
||||
struct ata_probe_ent ae;
|
||||
|
||||
struct ixp4xx_pata_data *data = pdev->dev.platform_data;
|
||||
|
||||
cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
|
||||
if (!cs0 || !cs1)
|
||||
return -EINVAL;
|
||||
|
||||
pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
|
||||
|
||||
data->cs0 = ioremap(cs0->start, 0x1000);
|
||||
data->cs1 = ioremap(cs1->start, 0x1000);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq)
|
||||
set_irq_type(irq, IRQT_HIGH);
|
||||
|
||||
/* Setup expansion bus chip selects */
|
||||
*data->cs0_cfg = data->cs0_bits;
|
||||
*data->cs1_cfg = data->cs1_bits;
|
||||
|
||||
memset(&ae, 0, sizeof(struct ata_probe_ent));
|
||||
INIT_LIST_HEAD(&ae.node);
|
||||
|
||||
ae.dev = &pdev->dev;
|
||||
ae.port_ops = &ixp4xx_port_ops;
|
||||
ae.sht = &ixp4xx_sht;
|
||||
ae.n_ports = 1;
|
||||
ae.pio_mask = 0x1f; /* PIO4 */
|
||||
ae.irq = irq;
|
||||
ae.irq_flags = 0;
|
||||
ae.port_flags = ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
|
||||
| ATA_FLAG_NO_ATAPI | ATA_FLAG_SRST;
|
||||
|
||||
/* run in polling mode if no irq has been assigned */
|
||||
if (!irq)
|
||||
ae.port_flags |= ATA_FLAG_PIO_POLLING;
|
||||
|
||||
ixp4xx_setup_port(&ae.port[0], data);
|
||||
|
||||
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
ret = ata_device_add(&ae);
|
||||
if (ret == 0)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
|
||||
{
|
||||
struct ata_host *host = platform_get_drvdata(dev);
|
||||
|
||||
ata_host_remove(host);
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ixp4xx_pata_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ixp4xx_pata_probe,
|
||||
.remove = __devexit_p(ixp4xx_pata_remove),
|
||||
};
|
||||
|
||||
static int __init ixp4xx_pata_init(void)
|
||||
{
|
||||
return platform_driver_register(&ixp4xx_pata_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit ixp4xx_pata_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ixp4xx_pata_platform_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <[email protected]>");
|
||||
MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
module_init(ixp4xx_pata_init);
|
||||
module_exit(ixp4xx_pata_exit);
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_jmicron"
|
||||
#define DRV_VERSION "0.1.2"
|
||||
#define DRV_VERSION "0.1.4"
|
||||
|
||||
typedef enum {
|
||||
PORT_PATA0 = 0,
|
||||
|
|
@ -128,8 +128,6 @@ static struct scsi_host_template jmicron_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
/* Special handling needed if you have sector or LBA48 limits */
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -213,12 +211,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
|
|||
|
||||
/* FIXME: We may want a way to override this in future */
|
||||
pci_write_config_byte(pdev, 0x41, 0xa1);
|
||||
|
||||
/* PATA controller is fn 1, AHCI is fn 0 */
|
||||
if (PCI_FUNC(pdev->devfn) != 1)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* PATA controller is fn 1, AHCI is fn 0 */
|
||||
if (PCI_FUNC(pdev->devfn) != 1)
|
||||
return -ENODEV;
|
||||
|
||||
if ( id->driver_data == 365 || id->driver_data == 366) {
|
||||
/* The 365/66 have two PATA channels, redirect the second */
|
||||
pci_read_config_dword(pdev, 0x80, ®);
|
||||
|
|
@ -229,6 +226,27 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
|
|||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int jmicron_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
switch(pdev->device) {
|
||||
case PCI_DEVICE_ID_JMICRON_JMB368:
|
||||
break;
|
||||
case PCI_DEVICE_ID_JMICRON_JMB365:
|
||||
case PCI_DEVICE_ID_JMICRON_JMB366:
|
||||
/* Restore mapping or disks swap and boy does it get ugly */
|
||||
pci_read_config_dword(pdev, 0x80, ®);
|
||||
reg |= (1 << 24); /* IDE1 to PATA IDE secondary */
|
||||
pci_write_config_dword(pdev, 0x80, reg);
|
||||
/* Fall through */
|
||||
default:
|
||||
/* Make sure AHCI is turned back on */
|
||||
pci_write_config_byte(pdev, 0x41, 0xa1);
|
||||
}
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id jmicron_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361},
|
||||
{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363},
|
||||
|
|
@ -244,6 +262,8 @@ static struct pci_driver jmicron_pci_driver = {
|
|||
.id_table = jmicron_pci_tbl,
|
||||
.probe = jmicron_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = jmicron_reinit_one,
|
||||
};
|
||||
|
||||
static int __init jmicron_init(void)
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ static struct scsi_host_template legacy_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
224
drivers/ata/pata_marvell.c
Normal file
224
drivers/ata/pata_marvell.c
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Marvell PATA driver.
|
||||
*
|
||||
* For the moment we drive the PATA port in legacy mode. That
|
||||
* isn't making full use of the device functionality but it is
|
||||
* easy to get working.
|
||||
*
|
||||
* (c) 2006 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 <linux/libata.h>
|
||||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_marvell"
|
||||
#define DRV_VERSION "0.1.1"
|
||||
|
||||
/**
|
||||
* marvell_pre_reset - check for 40/80 pin
|
||||
* @ap: Port
|
||||
*
|
||||
* Perform the PATA port setup we need.
|
||||
*/
|
||||
|
||||
static int marvell_pre_reset(struct ata_port *ap)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 devices;
|
||||
void __iomem *barp;
|
||||
int i;
|
||||
|
||||
/* Check if our port is enabled */
|
||||
|
||||
barp = pci_iomap(pdev, 5, 0x10);
|
||||
if (barp == NULL)
|
||||
return -ENOMEM;
|
||||
printk("BAR5:");
|
||||
for(i = 0; i <= 0x0F; i++)
|
||||
printk("%02X:%02X ", i, readb(barp + i));
|
||||
printk("\n");
|
||||
|
||||
devices = readl(barp + 0x0C);
|
||||
pci_iounmap(pdev, barp);
|
||||
|
||||
if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
|
||||
(!(devices & 0x10))) /* PATA enable ? */
|
||||
return -ENOENT;
|
||||
|
||||
/* Cable type */
|
||||
switch(ap->port_no)
|
||||
{
|
||||
case 0:
|
||||
if (inb(ap->ioaddr.bmdma_addr + 1) & 1)
|
||||
ap->cbl = ATA_CBL_PATA40;
|
||||
else
|
||||
ap->cbl = ATA_CBL_PATA80;
|
||||
break;
|
||||
|
||||
case 1: /* Legacy SATA port */
|
||||
ap->cbl = ATA_CBL_SATA;
|
||||
break;
|
||||
}
|
||||
return ata_std_prereset(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* marvell_error_handler - Setup and error handler
|
||||
* @ap: Port to handle
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*/
|
||||
|
||||
static void marvell_error_handler(struct ata_port *ap)
|
||||
{
|
||||
return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset,
|
||||
NULL, ata_std_postreset);
|
||||
}
|
||||
|
||||
/* No PIO or DMA methods needed for this device */
|
||||
|
||||
static struct scsi_host_template marvell_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,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations marvell_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
|
||||
/* 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 = marvell_error_handler,
|
||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||
|
||||
/* 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 = ata_qc_issue_prot,
|
||||
.data_xfer = ata_pio_data_xfer,
|
||||
|
||||
/* Timeout handling */
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ata_bmdma_irq_clear,
|
||||
|
||||
/* Generic PATA PCI ATA helpers */
|
||||
.port_start = ata_port_start,
|
||||
.port_stop = ata_port_stop,
|
||||
.host_stop = ata_host_stop,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* marvell_init_one - Register Marvell ATA PCI device with kernel services
|
||||
* @pdev: PCI device to register
|
||||
* @ent: Entry in marvell_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 marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
static struct ata_port_info info = {
|
||||
.sht = &marvell_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x3f,
|
||||
|
||||
.port_ops = &marvell_ops,
|
||||
};
|
||||
static struct ata_port_info info_sata = {
|
||||
.sht = &marvell_sht,
|
||||
/* Slave possible as its magically mapped not real */
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7f,
|
||||
|
||||
.port_ops = &marvell_ops,
|
||||
};
|
||||
struct ata_port_info *port_info[2] = { &info, &info_sata };
|
||||
int n_port = 2;
|
||||
|
||||
if (pdev->device == 0x6101)
|
||||
n_port = 1;
|
||||
|
||||
return ata_pci_init_one(pdev, port_info, n_port);
|
||||
}
|
||||
|
||||
static const struct pci_device_id marvell_pci_tbl[] = {
|
||||
{ PCI_DEVICE(0x11AB, 0x6101), },
|
||||
{ PCI_DEVICE(0x11AB, 0x6145), },
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
static struct pci_driver marvell_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = marvell_pci_tbl,
|
||||
.probe = marvell_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init marvell_init(void)
|
||||
{
|
||||
return pci_register_driver(&marvell_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit marvell_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&marvell_pci_driver);
|
||||
}
|
||||
|
||||
module_init(marvell_init);
|
||||
module_exit(marvell_exit);
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, marvell_pci_tbl);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_mpiix"
|
||||
#define DRV_VERSION "0.7.2"
|
||||
#define DRV_VERSION "0.7.3"
|
||||
|
||||
enum {
|
||||
IDETIM = 0x6C, /* IDE control register */
|
||||
|
|
@ -159,7 +159,6 @@ static struct scsi_host_template mpiix_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -168,6 +167,8 @@ static struct scsi_host_template mpiix_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations mpiix_port_ops = {
|
||||
|
|
@ -285,7 +286,9 @@ static struct pci_driver mpiix_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = mpiix,
|
||||
.probe = mpiix_init_one,
|
||||
.remove = mpiix_remove_one
|
||||
.remove = mpiix_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init mpiix_init(void)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_netcell"
|
||||
#define DRV_VERSION "0.1.5"
|
||||
#define DRV_VERSION "0.1.6"
|
||||
|
||||
/**
|
||||
* netcell_probe_init - check for 40/80 pin
|
||||
|
|
@ -54,8 +54,6 @@ static struct scsi_host_template netcell_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
/* Special handling needed if you have sector or LBA48 limits */
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -65,6 +63,8 @@ static struct scsi_host_template netcell_sht = {
|
|||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
/* Use standard CHS mapping rules */
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations netcell_ops = {
|
||||
|
|
@ -153,6 +153,8 @@ static struct pci_driver netcell_pci_driver = {
|
|||
.id_table = netcell_pci_tbl,
|
||||
.probe = netcell_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init netcell_init(void)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_ns87410"
|
||||
#define DRV_VERSION "0.4.2"
|
||||
#define DRV_VERSION "0.4.3"
|
||||
|
||||
/**
|
||||
* ns87410_pre_reset - probe begin
|
||||
|
|
@ -149,7 +149,6 @@ static struct scsi_host_template ns87410_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -158,6 +157,8 @@ static struct scsi_host_template ns87410_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations ns87410_port_ops = {
|
||||
|
|
@ -210,7 +211,9 @@ static struct pci_driver ns87410_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = ns87410,
|
||||
.probe = ns87410_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init ns87410_init(void)
|
||||
|
|
|
|||
|
|
@ -224,7 +224,6 @@ static struct scsi_host_template oldpiix_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -233,6 +232,8 @@ static struct scsi_host_template oldpiix_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations oldpiix_pata_ops = {
|
||||
|
|
@ -314,6 +315,8 @@ static struct pci_driver oldpiix_pci_driver = {
|
|||
.id_table = oldpiix_pci_tbl,
|
||||
.probe = oldpiix_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init oldpiix_init(void)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_opti"
|
||||
#define DRV_VERSION "0.2.5"
|
||||
#define DRV_VERSION "0.2.7"
|
||||
|
||||
enum {
|
||||
READ_REG = 0, /* index of Read cycle timing register */
|
||||
|
|
@ -109,30 +109,6 @@ static void opti_write_reg(struct ata_port *ap, u8 val, int reg)
|
|||
outb(0x83, regio + 2);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* opti_read_reg - control register read
|
||||
* @ap: ATA port
|
||||
* @reg: control register number
|
||||
*
|
||||
* The Opti uses magic 'trapdoor' register accesses to do configuration
|
||||
* rather than using PCI space as other controllers do. The double inw
|
||||
* on the error register activates configuration mode. We can then read
|
||||
* the control register
|
||||
*/
|
||||
|
||||
static u8 opti_read_reg(struct ata_port *ap, int reg)
|
||||
{
|
||||
unsigned long regio = ap->ioaddr.cmd_addr;
|
||||
u8 ret;
|
||||
inw(regio + 1);
|
||||
inw(regio + 1);
|
||||
outb(3, regio + 2);
|
||||
ret = inb(regio + reg);
|
||||
outb(0x83, regio + 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* opti_set_piomode - set initial PIO mode data
|
||||
* @ap: ATA interface
|
||||
|
|
@ -195,7 +171,6 @@ static struct scsi_host_template opti_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -204,12 +179,13 @@ static struct scsi_host_template opti_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations opti_port_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
.set_piomode = opti_set_piomode,
|
||||
/* .set_dmamode = opti_set_dmamode, */
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
.check_status = ata_check_status,
|
||||
|
|
@ -267,7 +243,9 @@ static struct pci_driver opti_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = opti,
|
||||
.probe = opti_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init opti_init(void)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_optidma"
|
||||
#define DRV_VERSION "0.2.2"
|
||||
#define DRV_VERSION "0.2.3"
|
||||
|
||||
enum {
|
||||
READ_REG = 0, /* index of Read cycle timing register */
|
||||
|
|
@ -352,7 +352,6 @@ static struct scsi_host_template optidma_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -361,6 +360,8 @@ static struct scsi_host_template optidma_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations optidma_port_ops = {
|
||||
|
|
@ -522,7 +523,9 @@ static struct pci_driver optidma_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = optidma,
|
||||
.probe = optidma_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init optidma_init(void)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ static struct scsi_host_template pcmcia_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -134,7 +134,6 @@ static struct scsi_host_template pdc2027x_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -854,7 +853,7 @@ static void __devexit pdc2027x_remove_one(struct pci_dev *pdev)
|
|||
*/
|
||||
static int __init pdc2027x_init(void)
|
||||
{
|
||||
return pci_module_init(&pdc2027x_pci_driver);
|
||||
return pci_register_driver(&pdc2027x_pci_driver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_pdc202xx_old"
|
||||
#define DRV_VERSION "0.2.1"
|
||||
#define DRV_VERSION "0.2.3"
|
||||
|
||||
/**
|
||||
* pdc2024x_pre_reset - probe begin
|
||||
|
|
@ -63,7 +63,7 @@ static void pdc2026x_error_handler(struct ata_port *ap)
|
|||
}
|
||||
|
||||
/**
|
||||
* pdc_configure_piomode - set chip PIO timing
|
||||
* pdc202xx_configure_piomode - set chip PIO timing
|
||||
* @ap: ATA interface
|
||||
* @adev: ATA device
|
||||
* @pio: PIO mode
|
||||
|
|
@ -73,7 +73,7 @@ static void pdc2026x_error_handler(struct ata_port *ap)
|
|||
* versa
|
||||
*/
|
||||
|
||||
static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio)
|
||||
static void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
int port = 0x60 + 4 * ap->port_no + 2 * adev->devno;
|
||||
|
|
@ -98,7 +98,7 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev,
|
|||
}
|
||||
|
||||
/**
|
||||
* pdc_set_piomode - set initial PIO mode data
|
||||
* pdc202xx_set_piomode - set initial PIO mode data
|
||||
* @ap: ATA interface
|
||||
* @adev: ATA device
|
||||
*
|
||||
|
|
@ -106,13 +106,13 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev,
|
|||
* but we want to set the PIO timing by default.
|
||||
*/
|
||||
|
||||
static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
static void pdc202xx_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
pdc_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
|
||||
pdc202xx_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pdc_configure_dmamode - set DMA mode in chip
|
||||
* pdc202xx_configure_dmamode - set DMA mode in chip
|
||||
* @ap: ATA interface
|
||||
* @adev: ATA device
|
||||
*
|
||||
|
|
@ -120,7 +120,7 @@ static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||
* to occur.
|
||||
*/
|
||||
|
||||
static void pdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
int port = 0x60 + 4 * ap->port_no + 2 * adev->devno;
|
||||
|
|
@ -184,7 +184,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
|
|||
|
||||
/* The DMA clocks may have been trashed by a reset. FIXME: make conditional
|
||||
and move to qc_issue ? */
|
||||
pdc_set_dmamode(ap, qc->dev);
|
||||
pdc202xx_set_dmamode(ap, qc->dev);
|
||||
|
||||
/* Cases the state machine will not complete correctly without help */
|
||||
if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA)
|
||||
|
|
@ -254,7 +254,7 @@ static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev)
|
|||
adev->max_sectors = 256;
|
||||
}
|
||||
|
||||
static struct scsi_host_template pdc_sht = {
|
||||
static struct scsi_host_template pdc202xx_sht = {
|
||||
.module = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
|
|
@ -262,7 +262,6 @@ static struct scsi_host_template pdc_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -271,12 +270,14 @@ static struct scsi_host_template pdc_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations pdc2024x_port_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
.set_piomode = pdc_set_piomode,
|
||||
.set_dmamode = pdc_set_dmamode,
|
||||
.set_piomode = pdc202xx_set_piomode,
|
||||
.set_dmamode = pdc202xx_set_dmamode,
|
||||
.mode_filter = ata_pci_default_filter,
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
|
|
@ -308,8 +309,8 @@ static struct ata_port_operations pdc2024x_port_ops = {
|
|||
|
||||
static struct ata_port_operations pdc2026x_port_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
.set_piomode = pdc_set_piomode,
|
||||
.set_dmamode = pdc_set_dmamode,
|
||||
.set_piomode = pdc202xx_set_piomode,
|
||||
.set_dmamode = pdc202xx_set_dmamode,
|
||||
.mode_filter = ata_pci_default_filter,
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
|
|
@ -340,11 +341,11 @@ static struct ata_port_operations pdc2026x_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
static int pdc_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)
|
||||
{
|
||||
static struct ata_port_info info[3] = {
|
||||
{
|
||||
.sht = &pdc_sht,
|
||||
.sht = &pdc202xx_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
|
|
@ -352,7 +353,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
.port_ops = &pdc2024x_port_ops
|
||||
},
|
||||
{
|
||||
.sht = &pdc_sht,
|
||||
.sht = &pdc202xx_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
|
|
@ -360,7 +361,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
.port_ops = &pdc2026x_port_ops
|
||||
},
|
||||
{
|
||||
.sht = &pdc_sht,
|
||||
.sht = &pdc202xx_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
|
|
@ -386,7 +387,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(dev, port_info, 2);
|
||||
}
|
||||
|
||||
static const struct pci_device_id pdc[] = {
|
||||
static const struct pci_device_id pdc202xx[] = {
|
||||
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
|
||||
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
|
||||
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
|
||||
|
|
@ -396,28 +397,30 @@ static const struct pci_device_id pdc[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static struct pci_driver pdc_pci_driver = {
|
||||
static struct pci_driver pdc202xx_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = pdc,
|
||||
.probe = pdc_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.id_table = pdc202xx,
|
||||
.probe = pdc202xx_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init pdc_init(void)
|
||||
static int __init pdc202xx_init(void)
|
||||
{
|
||||
return pci_register_driver(&pdc_pci_driver);
|
||||
return pci_register_driver(&pdc202xx_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit pdc_exit(void)
|
||||
static void __exit pdc202xx_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&pdc_pci_driver);
|
||||
pci_unregister_driver(&pdc202xx_pci_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, pdc);
|
||||
MODULE_DEVICE_TABLE(pci, pdc202xx);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
module_init(pdc_init);
|
||||
module_exit(pdc_exit);
|
||||
module_init(pdc202xx_init);
|
||||
module_exit(pdc202xx_exit);
|
||||
|
|
|
|||
295
drivers/ata/pata_platform.c
Normal file
295
drivers/ata/pata_platform.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* Generic platform device PATA driver
|
||||
*
|
||||
* Copyright (C) 2006 Paul Mundt
|
||||
*
|
||||
* Based on pata_pcmcia:
|
||||
*
|
||||
* Copyright 2005-2006 Red Hat Inc <alan@redhat.com>, all rights reserved.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <linux/ata.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pata_platform.h>
|
||||
|
||||
#define DRV_NAME "pata_platform"
|
||||
#define DRV_VERSION "0.1.2"
|
||||
|
||||
static int pio_mask = 1;
|
||||
|
||||
/*
|
||||
* Provide our own set_mode() as we don't want to change anything that has
|
||||
* already been configured..
|
||||
*/
|
||||
static void pata_platform_set_mode(struct ata_port *ap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
struct ata_device *dev = &ap->device[i];
|
||||
|
||||
if (ata_dev_enabled(dev)) {
|
||||
/* We don't really care */
|
||||
dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
|
||||
dev->xfer_shift = ATA_SHIFT_PIO;
|
||||
dev->flags |= ATA_DFLAG_PIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pata_platform_host_stop(struct ata_host *host)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Unmap the bases for MMIO
|
||||
*/
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
|
||||
if (ap->flags & ATA_FLAG_MMIO) {
|
||||
iounmap((void __iomem *)ap->ioaddr.ctl_addr);
|
||||
iounmap((void __iomem *)ap->ioaddr.cmd_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct scsi_host_template pata_platform_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 pata_platform_port_ops = {
|
||||
.set_mode = pata_platform_set_mode,
|
||||
|
||||
.port_disable = ata_port_disable,
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
.check_status = ata_check_status,
|
||||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.freeze = ata_bmdma_freeze,
|
||||
.thaw = ata_bmdma_thaw,
|
||||
.error_handler = ata_bmdma_error_handler,
|
||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||
|
||||
.qc_prep = ata_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
|
||||
.data_xfer = ata_pio_data_xfer_noirq,
|
||||
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ata_bmdma_irq_clear,
|
||||
|
||||
.port_start = ata_port_start,
|
||||
.port_stop = ata_port_stop,
|
||||
.host_stop = pata_platform_host_stop
|
||||
};
|
||||
|
||||
static void pata_platform_setup_port(struct ata_ioports *ioaddr,
|
||||
struct pata_platform_info *info)
|
||||
{
|
||||
unsigned int shift = 0;
|
||||
|
||||
/* Fixup the port shift for platforms that need it */
|
||||
if (info && info->ioport_shift)
|
||||
shift = info->ioport_shift;
|
||||
|
||||
ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift);
|
||||
ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift);
|
||||
ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
|
||||
ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << shift);
|
||||
ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << shift);
|
||||
ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << shift);
|
||||
ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << shift);
|
||||
ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << shift);
|
||||
ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << shift);
|
||||
ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << shift);
|
||||
}
|
||||
|
||||
/**
|
||||
* pata_platform_probe - attach a platform interface
|
||||
* @pdev: platform device
|
||||
*
|
||||
* Register a platform bus IDE interface. Such interfaces are PIO and we
|
||||
* assume do not support IRQ sharing.
|
||||
*
|
||||
* Platform devices are expected to contain 3 resources per port:
|
||||
*
|
||||
* - I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
|
||||
* - CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
|
||||
* - IRQ (IORESOURCE_IRQ)
|
||||
*
|
||||
* If the base resources are both mem types, the ioremap() is handled
|
||||
* here. For IORESOURCE_IO, it's assumed that there's no remapping
|
||||
* necessary.
|
||||
*/
|
||||
static int __devinit pata_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *io_res, *ctl_res;
|
||||
struct ata_probe_ent ae;
|
||||
unsigned int mmio;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Simple resource validation ..
|
||||
*/
|
||||
if (unlikely(pdev->num_resources != 3)) {
|
||||
dev_err(&pdev->dev, "invalid number of resources\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the I/O base first
|
||||
*/
|
||||
io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||
if (io_res == NULL) {
|
||||
io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(io_res == NULL))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Then the CTL base
|
||||
*/
|
||||
ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
||||
if (ctl_res == NULL) {
|
||||
ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (unlikely(ctl_res == NULL))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for MMIO
|
||||
*/
|
||||
mmio = (( io_res->flags == IORESOURCE_MEM) &&
|
||||
(ctl_res->flags == IORESOURCE_MEM));
|
||||
|
||||
/*
|
||||
* Now that that's out of the way, wire up the port..
|
||||
*/
|
||||
memset(&ae, 0, sizeof(struct ata_probe_ent));
|
||||
INIT_LIST_HEAD(&ae.node);
|
||||
ae.dev = &pdev->dev;
|
||||
ae.port_ops = &pata_platform_port_ops;
|
||||
ae.sht = &pata_platform_sht;
|
||||
ae.n_ports = 1;
|
||||
ae.pio_mask = pio_mask;
|
||||
ae.irq = platform_get_irq(pdev, 0);
|
||||
ae.irq_flags = 0;
|
||||
ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
|
||||
|
||||
/*
|
||||
* Handle the MMIO case
|
||||
*/
|
||||
if (mmio) {
|
||||
ae.port_flags |= ATA_FLAG_MMIO;
|
||||
|
||||
ae.port[0].cmd_addr = (unsigned long)ioremap(io_res->start,
|
||||
io_res->end - io_res->start + 1);
|
||||
if (unlikely(!ae.port[0].cmd_addr)) {
|
||||
dev_err(&pdev->dev, "failed to remap IO base\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ae.port[0].ctl_addr = (unsigned long)ioremap(ctl_res->start,
|
||||
ctl_res->end - ctl_res->start + 1);
|
||||
if (unlikely(!ae.port[0].ctl_addr)) {
|
||||
dev_err(&pdev->dev, "failed to remap CTL base\n");
|
||||
ret = -ENXIO;
|
||||
goto bad_remap;
|
||||
}
|
||||
} else {
|
||||
ae.port[0].cmd_addr = io_res->start;
|
||||
ae.port[0].ctl_addr = ctl_res->start;
|
||||
}
|
||||
|
||||
ae.port[0].altstatus_addr = ae.port[0].ctl_addr;
|
||||
|
||||
pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data);
|
||||
|
||||
if (unlikely(ata_device_add(&ae) == 0)) {
|
||||
ret = -ENODEV;
|
||||
goto add_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
add_failed:
|
||||
if (ae.port[0].ctl_addr && mmio)
|
||||
iounmap((void __iomem *)ae.port[0].ctl_addr);
|
||||
bad_remap:
|
||||
if (ae.port[0].cmd_addr && mmio)
|
||||
iounmap((void __iomem *)ae.port[0].cmd_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pata_platform_remove - unplug a platform interface
|
||||
* @pdev: platform device
|
||||
*
|
||||
* A platform bus ATA device has been unplugged. Perform the needed
|
||||
* cleanup. Also called on module unload for any active devices.
|
||||
*/
|
||||
static int __devexit pata_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ata_host *host = dev_get_drvdata(dev);
|
||||
|
||||
ata_host_remove(host);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pata_platform_driver = {
|
||||
.probe = pata_platform_probe,
|
||||
.remove = __devexit_p(pata_platform_remove),
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_platform_init(void)
|
||||
{
|
||||
return platform_driver_register(&pata_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit pata_platform_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pata_platform_driver);
|
||||
}
|
||||
module_init(pata_platform_init);
|
||||
module_exit(pata_platform_exit);
|
||||
|
||||
module_param(pio_mask, int, 0);
|
||||
|
||||
MODULE_AUTHOR("Paul Mundt");
|
||||
MODULE_DESCRIPTION("low-level driver for platform device ATA");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
|
@ -157,7 +157,6 @@ static struct scsi_host_template qdi_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ static struct scsi_host_template radisys_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -229,6 +228,8 @@ static struct scsi_host_template radisys_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations radisys_pata_ops = {
|
||||
|
|
@ -311,6 +312,8 @@ static struct pci_driver radisys_pci_driver = {
|
|||
.id_table = radisys_pci_tbl,
|
||||
.probe = radisys_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init radisys_init(void)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_rz1000"
|
||||
#define DRV_VERSION "0.2.2"
|
||||
#define DRV_VERSION "0.2.3"
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -83,7 +83,6 @@ static struct scsi_host_template rz1000_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -92,6 +91,8 @@ static struct scsi_host_template rz1000_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations rz1000_port_ops = {
|
||||
|
|
@ -129,6 +130,19 @@ static struct ata_port_operations rz1000_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
static int rz1000_fifo_disable(struct pci_dev *pdev)
|
||||
{
|
||||
u16 reg;
|
||||
/* Be exceptionally paranoid as we must be sure to apply the fix */
|
||||
if (pci_read_config_word(pdev, 0x40, ®) != 0)
|
||||
return -1;
|
||||
reg &= 0xDFFF;
|
||||
if (pci_write_config_word(pdev, 0x40, reg) != 0)
|
||||
return -1;
|
||||
printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rz1000_init_one - Register RZ1000 ATA PCI device with kernel services
|
||||
* @pdev: PCI device to register
|
||||
|
|
@ -143,7 +157,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
|
|||
{
|
||||
static int printed_version;
|
||||
struct ata_port_info *port_info[2];
|
||||
u16 reg;
|
||||
static struct ata_port_info info = {
|
||||
.sht = &rz1000_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
|
|
@ -154,23 +167,25 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
|
|||
if (!printed_version++)
|
||||
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
|
||||
|
||||
/* Be exceptionally paranoid as we must be sure to apply the fix */
|
||||
if (pci_read_config_word(pdev, 0x40, ®) != 0)
|
||||
goto fail;
|
||||
reg &= 0xDFFF;
|
||||
if (pci_write_config_word(pdev, 0x40, reg) != 0)
|
||||
goto fail;
|
||||
printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n");
|
||||
|
||||
port_info[0] = &info;
|
||||
port_info[1] = &info;
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
fail:
|
||||
if (rz1000_fifo_disable(pdev) == 0) {
|
||||
port_info[0] = &info;
|
||||
port_info[1] = &info;
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n");
|
||||
/* Not safe to use so skip */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int rz1000_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
/* If this fails on resume (which is a "cant happen" case), we
|
||||
must stop as any progress risks data loss */
|
||||
if (rz1000_fifo_disable(pdev))
|
||||
panic("rz1000 fifo");
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id pata_rz1000[] = {
|
||||
{ PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), },
|
||||
{ PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), },
|
||||
|
|
@ -182,7 +197,9 @@ static struct pci_driver rz1000_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = pata_rz1000,
|
||||
.probe = rz1000_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = rz1000_reinit_one,
|
||||
};
|
||||
|
||||
static int __init rz1000_init(void)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "sc1200"
|
||||
#define DRV_VERSION "0.2.3"
|
||||
#define DRV_VERSION "0.2.4"
|
||||
|
||||
#define SC1200_REV_A 0x00
|
||||
#define SC1200_REV_B1 0x01
|
||||
|
|
@ -186,7 +186,6 @@ static struct scsi_host_template sc1200_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -195,6 +194,8 @@ static struct scsi_host_template sc1200_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations sc1200_port_ops = {
|
||||
|
|
@ -264,7 +265,9 @@ static struct pci_driver sc1200_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = sc1200,
|
||||
.probe = sc1200_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init sc1200_init(void)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_serverworks"
|
||||
#define DRV_VERSION "0.3.7"
|
||||
#define DRV_VERSION "0.3.9"
|
||||
|
||||
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
|
||||
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
|
||||
|
|
@ -318,7 +318,6 @@ static struct scsi_host_template serverworks_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -327,6 +326,8 @@ static struct scsi_host_template serverworks_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations serverworks_osb4_port_ops = {
|
||||
|
|
@ -554,6 +555,30 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
|
|||
return ata_pci_init_one(pdev, port_info, ports);
|
||||
}
|
||||
|
||||
static int serverworks_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
/* Force master latency timer to 64 PCI clocks */
|
||||
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
|
||||
|
||||
switch (pdev->device)
|
||||
{
|
||||
case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
|
||||
serverworks_fixup_osb4(pdev);
|
||||
break;
|
||||
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
|
||||
ata_pci_clear_simplex(pdev);
|
||||
/* fall through */
|
||||
case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
|
||||
case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
|
||||
serverworks_fixup_csb(pdev);
|
||||
break;
|
||||
case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
|
||||
serverworks_fixup_ht1000(pdev);
|
||||
break;
|
||||
}
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id serverworks[] = {
|
||||
{ PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0},
|
||||
{ PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2},
|
||||
|
|
@ -568,7 +593,9 @@ static struct pci_driver serverworks_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = serverworks,
|
||||
.probe = serverworks_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = serverworks_reinit_one,
|
||||
};
|
||||
|
||||
static int __init serverworks_init(void)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_sil680"
|
||||
#define DRV_VERSION "0.3.2"
|
||||
#define DRV_VERSION "0.4.1"
|
||||
|
||||
/**
|
||||
* sil680_selreg - return register base
|
||||
|
|
@ -218,7 +218,6 @@ static struct scsi_host_template sil680_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -263,32 +262,20 @@ static struct ata_port_operations sil680_port_ops = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
/**
|
||||
* sil680_init_chip - chip setup
|
||||
* @pdev: PCI device
|
||||
*
|
||||
* Perform all the chip setup which must be done both when the device
|
||||
* is powered up on boot and when we resume in case we resumed from RAM.
|
||||
* Returns the final clock settings.
|
||||
*/
|
||||
|
||||
static u8 sil680_init_chip(struct pci_dev *pdev)
|
||||
{
|
||||
static struct ata_port_info info = {
|
||||
.sht = &sil680_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7f,
|
||||
.port_ops = &sil680_port_ops
|
||||
};
|
||||
static struct ata_port_info info_slow = {
|
||||
.sht = &sil680_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x3f,
|
||||
.port_ops = &sil680_port_ops
|
||||
};
|
||||
static struct ata_port_info *port_info[2] = {&info, &info};
|
||||
static int printed_version;
|
||||
u32 class_rev = 0;
|
||||
u8 tmpbyte = 0;
|
||||
|
||||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xff;
|
||||
/* FIXME: double check */
|
||||
|
|
@ -323,8 +310,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
|
||||
printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
|
||||
tmpbyte & 1, tmpbyte & 0x30);
|
||||
if ((tmpbyte & 0x30) == 0)
|
||||
port_info[0] = port_info[1] = &info_slow;
|
||||
|
||||
pci_write_config_byte(pdev, 0xA1, 0x72);
|
||||
pci_write_config_word(pdev, 0xA2, 0x328A);
|
||||
|
|
@ -343,11 +328,51 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
|
||||
/* This last case is _NOT_ ok */
|
||||
case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
|
||||
return -EIO;
|
||||
}
|
||||
return tmpbyte & 0x30;
|
||||
}
|
||||
|
||||
static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
static struct ata_port_info info = {
|
||||
.sht = &sil680_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7f,
|
||||
.port_ops = &sil680_port_ops
|
||||
};
|
||||
static struct ata_port_info info_slow = {
|
||||
.sht = &sil680_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x3f,
|
||||
.port_ops = &sil680_port_ops
|
||||
};
|
||||
static struct ata_port_info *port_info[2] = {&info, &info};
|
||||
static int printed_version;
|
||||
|
||||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
switch(sil680_init_chip(pdev))
|
||||
{
|
||||
case 0:
|
||||
port_info[0] = port_info[1] = &info_slow;
|
||||
break;
|
||||
case 0x30:
|
||||
return -ENODEV;
|
||||
}
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
static int sil680_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
sil680_init_chip(pdev);
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id sil680[] = {
|
||||
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },
|
||||
|
||||
|
|
@ -358,7 +383,9 @@ static struct pci_driver sil680_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = sil680,
|
||||
.probe = sil680_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = sil680_reinit_one,
|
||||
};
|
||||
|
||||
static int __init sil680_init(void)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_sis"
|
||||
#define DRV_VERSION "0.4.4"
|
||||
#define DRV_VERSION "0.4.5"
|
||||
|
||||
struct sis_chipset {
|
||||
u16 device; /* PCI host ID */
|
||||
|
|
@ -538,7 +538,6 @@ static struct scsi_host_template sis_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -547,6 +546,8 @@ static struct scsi_host_template sis_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations sis_133_ops = {
|
||||
|
|
@ -1000,6 +1001,8 @@ static struct pci_driver sis_pci_driver = {
|
|||
.id_table = sis_pci_tbl,
|
||||
.probe = sis_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init sis_init(void)
|
||||
|
|
|
|||
|
|
@ -230,7 +230,6 @@ static struct scsi_host_template sl82c105_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_triflex"
|
||||
#define DRV_VERSION "0.2.5"
|
||||
#define DRV_VERSION "0.2.7"
|
||||
|
||||
/**
|
||||
* triflex_prereset - probe begin
|
||||
|
|
@ -185,7 +185,6 @@ static struct scsi_host_template triflex_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -194,6 +193,8 @@ static struct scsi_host_template triflex_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations triflex_port_ops = {
|
||||
|
|
@ -258,7 +259,9 @@ static struct pci_driver triflex_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = triflex,
|
||||
.probe = triflex_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
};
|
||||
|
||||
static int __init triflex_init(void)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
* VIA VT8233c - UDMA100
|
||||
* VIA VT8235 - UDMA133
|
||||
* VIA VT8237 - UDMA133
|
||||
* VIA VT8251 - UDMA133
|
||||
*
|
||||
* Most registers remain compatible across chips. Others start reserved
|
||||
* and acquire sensible semantics if set to 1 (eg cable detect). A few
|
||||
|
|
@ -60,7 +61,7 @@
|
|||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_via"
|
||||
#define DRV_VERSION "0.1.14"
|
||||
#define DRV_VERSION "0.2.0"
|
||||
|
||||
/*
|
||||
* The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
|
||||
|
|
@ -94,6 +95,7 @@ static const struct via_isa_bridge {
|
|||
u8 rev_max;
|
||||
u16 flags;
|
||||
} via_isa_bridges[] = {
|
||||
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
|
||||
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
|
|
@ -288,7 +290,6 @@ static struct scsi_host_template via_sht = {
|
|||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
@ -297,6 +298,8 @@ static struct scsi_host_template via_sht = {
|
|||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
.resume = ata_scsi_device_resume,
|
||||
.suspend = ata_scsi_device_suspend,
|
||||
};
|
||||
|
||||
static struct ata_port_operations via_port_ops = {
|
||||
|
|
@ -369,9 +372,43 @@ static struct ata_port_operations via_port_ops_noirq = {
|
|||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
/**
|
||||
* via_config_fifo - set up the FIFO
|
||||
* @pdev: PCI device
|
||||
* @flags: configuration flags
|
||||
*
|
||||
* Set the FIFO properties for this device if neccessary. Used both on
|
||||
* set up and on and the resume path
|
||||
*/
|
||||
|
||||
static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)
|
||||
{
|
||||
u8 enable;
|
||||
|
||||
/* 0x40 low bits indicate enabled channels */
|
||||
pci_read_config_byte(pdev, 0x40 , &enable);
|
||||
enable &= 3;
|
||||
|
||||
if (flags & VIA_SET_FIFO) {
|
||||
u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
|
||||
u8 fifo;
|
||||
|
||||
pci_read_config_byte(pdev, 0x43, &fifo);
|
||||
|
||||
/* Clear PREQ# until DDACK# for errata */
|
||||
if (flags & VIA_BAD_PREQ)
|
||||
fifo &= 0x7F;
|
||||
else
|
||||
fifo &= 0x9f;
|
||||
/* Turn on FIFO for enabled channels */
|
||||
fifo |= fifo_setting[enable];
|
||||
pci_write_config_byte(pdev, 0x43, fifo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* via_init_one - discovery callback
|
||||
* @pdev: PCI device ID
|
||||
* @pdev: PCI device
|
||||
* @id: PCI table info
|
||||
*
|
||||
* A VIA IDE interface has been discovered. Figure out what revision
|
||||
|
|
@ -383,7 +420,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* Early VIA without UDMA support */
|
||||
static struct ata_port_info via_mwdma_info = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.port_ops = &via_port_ops
|
||||
|
|
@ -391,7 +428,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* Ditto with IRQ masking required */
|
||||
static struct ata_port_info via_mwdma_info_borked = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.port_ops = &via_port_ops_noirq,
|
||||
|
|
@ -399,7 +436,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* VIA UDMA 33 devices (and borked 66) */
|
||||
static struct ata_port_info via_udma33_info = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7,
|
||||
|
|
@ -408,7 +445,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* VIA UDMA 66 devices */
|
||||
static struct ata_port_info via_udma66_info = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x1f,
|
||||
|
|
@ -417,7 +454,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* VIA UDMA 100 devices */
|
||||
static struct ata_port_info via_udma100_info = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x3f,
|
||||
|
|
@ -426,7 +463,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* UDMA133 with bad AST (All current 133) */
|
||||
static struct ata_port_info via_udma133_info = {
|
||||
.sht = &via_sht,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7f, /* FIXME: should check north bridge */
|
||||
|
|
@ -471,21 +508,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
|
||||
/* Initialise the FIFO for the enabled channels. */
|
||||
if (config->flags & VIA_SET_FIFO) {
|
||||
u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
|
||||
u8 fifo;
|
||||
|
||||
pci_read_config_byte(pdev, 0x43, &fifo);
|
||||
|
||||
/* Clear PREQ# until DDACK# for errata */
|
||||
if (config->flags & VIA_BAD_PREQ)
|
||||
fifo &= 0x7F;
|
||||
else
|
||||
fifo &= 0x9f;
|
||||
/* Turn on FIFO for enabled channels */
|
||||
fifo |= fifo_setting[enable];
|
||||
pci_write_config_byte(pdev, 0x43, fifo);
|
||||
}
|
||||
via_config_fifo(pdev, config->flags);
|
||||
|
||||
/* Clock set up */
|
||||
switch(config->flags & VIA_UDMA) {
|
||||
case VIA_UDMA_NONE:
|
||||
|
|
@ -529,6 +553,39 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* via_reinit_one - reinit after resume
|
||||
* @pdev; PCI device
|
||||
*
|
||||
* Called when the VIA PATA device is resumed. We must then
|
||||
* reconfigure the fifo and other setup we may have altered. In
|
||||
* addition the kernel needs to have the resume methods on PCI
|
||||
* quirk supported.
|
||||
*/
|
||||
|
||||
static int via_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
u32 timing;
|
||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||
const struct via_isa_bridge *config = host->private_data;
|
||||
|
||||
via_config_fifo(pdev, config->flags);
|
||||
|
||||
if ((config->flags & VIA_UDMA) == VIA_UDMA_66) {
|
||||
/* The 66 MHz devices require we enable the clock */
|
||||
pci_read_config_dword(pdev, 0x50, &timing);
|
||||
timing |= 0x80008;
|
||||
pci_write_config_dword(pdev, 0x50, timing);
|
||||
}
|
||||
if (config->flags & VIA_BAD_CLK66) {
|
||||
/* Disable the 66MHz clock on problem devices */
|
||||
pci_read_config_dword(pdev, 0x50, &timing);
|
||||
timing &= ~0x80008;
|
||||
pci_write_config_dword(pdev, 0x50, timing);
|
||||
}
|
||||
return ata_pci_device_resume(pdev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id via[] = {
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), },
|
||||
|
|
@ -542,7 +599,9 @@ static struct pci_driver via_pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = via,
|
||||
.probe = via_init_one,
|
||||
.remove = ata_pci_remove_one
|
||||
.remove = ata_pci_remove_one,
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = via_reinit_one,
|
||||
};
|
||||
|
||||
static int __init via_init(void)
|
||||
|
|
|
|||
306
drivers/ata/pata_winbond.c
Normal file
306
drivers/ata/pata_winbond.c
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* pata_winbond.c - Winbond VLB ATA controllers
|
||||
* (C) 2006 Red Hat <alan@redhat.com>
|
||||
*
|
||||
* Support for the Winbond 83759A when operating in advanced mode.
|
||||
* Multichip mode is not currently supported.
|
||||
*/
|
||||
|
||||
#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 <scsi/scsi_host.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define DRV_NAME "pata_winbond"
|
||||
#define DRV_VERSION "0.0.1"
|
||||
|
||||
#define NR_HOST 4 /* Two winbond controllers, two channels each */
|
||||
|
||||
struct winbond_data {
|
||||
unsigned long config;
|
||||
struct platform_device *platform_dev;
|
||||
};
|
||||
|
||||
static struct ata_host *winbond_host[NR_HOST];
|
||||
static struct winbond_data winbond_data[NR_HOST];
|
||||
static int nr_winbond_host;
|
||||
|
||||
#ifdef MODULE
|
||||
static int probe_winbond = 1;
|
||||
#else
|
||||
static int probe_winbond;
|
||||
#endif
|
||||
|
||||
static spinlock_t winbond_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static void winbond_writecfg(unsigned long port, u8 reg, u8 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&winbond_lock, flags);
|
||||
outb(reg, port + 0x01);
|
||||
outb(val, port + 0x02);
|
||||
spin_unlock_irqrestore(&winbond_lock, flags);
|
||||
}
|
||||
|
||||
static u8 winbond_readcfg(unsigned long port, u8 reg)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&winbond_lock, flags);
|
||||
outb(reg, port + 0x01);
|
||||
val = inb(port + 0x02);
|
||||
spin_unlock_irqrestore(&winbond_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct ata_timing t;
|
||||
struct winbond_data *winbond = ap->host->private_data;
|
||||
int active, recovery;
|
||||
u8 reg;
|
||||
int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
|
||||
|
||||
reg = winbond_readcfg(winbond->config, 0x81);
|
||||
|
||||
/* Get the timing data in cycles */
|
||||
if (reg & 0x40) /* Fast VLB bus, assume 50MHz */
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
|
||||
else
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
active = (FIT(t.active, 3, 17) - 1) & 0x0F;
|
||||
recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
|
||||
timing = (active << 4) | recovery;
|
||||
winbond_writecfg(winbond->config, timing, reg);
|
||||
|
||||
/* Load the setup timing */
|
||||
|
||||
reg = 0x35;
|
||||
if (adev->class != ATA_DEV_ATA)
|
||||
reg |= 0x08; /* FIFO off */
|
||||
if (!ata_pio_need_iordy(adev))
|
||||
reg |= 0x02; /* IORDY off */
|
||||
reg |= (FIT(t.setup, 0, 3) << 6);
|
||||
winbond_writecfg(winbond->config, timing + 1, reg);
|
||||
}
|
||||
|
||||
|
||||
static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
|
||||
{
|
||||
struct ata_port *ap = adev->ap;
|
||||
int slop = buflen & 3;
|
||||
|
||||
if (ata_id_has_dword_io(adev->id)) {
|
||||
if (write_data)
|
||||
outsl(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||
else
|
||||
insl(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||
|
||||
if (unlikely(slop)) {
|
||||
u32 pad;
|
||||
if (write_data) {
|
||||
memcpy(&pad, buf + buflen - slop, slop);
|
||||
outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
||||
} else {
|
||||
pad = cpu_to_le16(inl(ap->ioaddr.data_addr));
|
||||
memcpy(buf + buflen - slop, &pad, slop);
|
||||
}
|
||||
}
|
||||
} else
|
||||
ata_pio_data_xfer(adev, buf, buflen, write_data);
|
||||
}
|
||||
|
||||
static struct scsi_host_template winbond_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 winbond_port_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
.set_piomode = winbond_set_piomode,
|
||||
|
||||
.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 = ata_bmdma_error_handler,
|
||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||
|
||||
.qc_prep = ata_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
|
||||
.data_xfer = winbond_data_xfer,
|
||||
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ata_bmdma_irq_clear,
|
||||
|
||||
.port_start = ata_port_start,
|
||||
.port_stop = ata_port_stop,
|
||||
.host_stop = ata_host_stop
|
||||
};
|
||||
|
||||
/**
|
||||
* winbond_init_one - attach a winbond interface
|
||||
* @type: Type to display
|
||||
* @io: I/O port start
|
||||
* @irq: interrupt line
|
||||
* @fast: True if on a > 33Mhz VLB
|
||||
*
|
||||
* Register a VLB bus IDE interface. Such interfaces are PIO and we
|
||||
* assume do not support IRQ sharing.
|
||||
*/
|
||||
|
||||
static __init int winbond_init_one(unsigned long port)
|
||||
{
|
||||
struct ata_probe_ent ae;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
u8 reg;
|
||||
int i;
|
||||
|
||||
reg = winbond_readcfg(port, 0x81);
|
||||
reg |= 0x80; /* jumpered mode off */
|
||||
winbond_writecfg(port, 0x81, reg);
|
||||
reg = winbond_readcfg(port, 0x83);
|
||||
reg |= 0xF0; /* local control */
|
||||
winbond_writecfg(port, 0x83, reg);
|
||||
reg = winbond_readcfg(port, 0x85);
|
||||
reg |= 0xF0; /* programmable timing */
|
||||
winbond_writecfg(port, 0x85, reg);
|
||||
|
||||
reg = winbond_readcfg(port, 0x81);
|
||||
|
||||
if (!(reg & 0x03)) /* Disabled */
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 2 ; i ++) {
|
||||
|
||||
if (reg & (1 << i)) {
|
||||
/*
|
||||
* Fill in a probe structure first of all
|
||||
*/
|
||||
|
||||
pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0);
|
||||
if (pdev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&ae, 0, sizeof(struct ata_probe_ent));
|
||||
INIT_LIST_HEAD(&ae.node);
|
||||
ae.dev = &pdev->dev;
|
||||
|
||||
ae.port_ops = &winbond_port_ops;
|
||||
ae.pio_mask = 0x1F;
|
||||
|
||||
ae.sht = &winbond_sht;
|
||||
|
||||
ae.n_ports = 1;
|
||||
ae.irq = 14 + i;
|
||||
ae.irq_flags = 0;
|
||||
ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
|
||||
ae.port[0].cmd_addr = 0x1F0 - (0x80 * i);
|
||||
ae.port[0].altstatus_addr = ae.port[0].cmd_addr + 0x0206;
|
||||
ae.port[0].ctl_addr = ae.port[0].altstatus_addr;
|
||||
ata_std_ports(&ae.port[0]);
|
||||
/*
|
||||
* Hook in a private data structure per channel
|
||||
*/
|
||||
ae.private_data = &winbond_data[nr_winbond_host];
|
||||
winbond_data[nr_winbond_host].config = port;
|
||||
winbond_data[nr_winbond_host].platform_dev = pdev;
|
||||
|
||||
ret = ata_device_add(&ae);
|
||||
if (ret == 0) {
|
||||
platform_device_unregister(pdev);
|
||||
return -ENODEV;
|
||||
}
|
||||
winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* winbond_init - attach winbond interfaces
|
||||
*
|
||||
* Attach winbond IDE interfaces by scanning the ports it may occupy.
|
||||
*/
|
||||
|
||||
static __init int winbond_init(void)
|
||||
{
|
||||
static const unsigned long config[2] = { 0x130, 0x1B0 };
|
||||
|
||||
int ct = 0;
|
||||
int i;
|
||||
|
||||
if (probe_winbond == 0)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Check both base addresses
|
||||
*/
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (probe_winbond & (1<<i)) {
|
||||
int ret = 0;
|
||||
unsigned long port = config[i];
|
||||
|
||||
if (request_region(port, 2, "pata_winbond")) {
|
||||
ret = winbond_init_one(port);
|
||||
if(ret <= 0)
|
||||
release_region(port, 2);
|
||||
else ct+= ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ct != 0)
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static __exit void winbond_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_winbond_host; i++) {
|
||||
ata_host_remove(winbond_host[i]);
|
||||
release_region(winbond_data[i].config, 2);
|
||||
platform_device_unregister(winbond_data[i].platform_dev);
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("low-level driver for Winbond VL ATA");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
module_init(winbond_init);
|
||||
module_exit(winbond_exit);
|
||||
|
||||
module_param(probe_winbond, int, 0);
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -46,20 +46,19 @@
|
|||
#include "sata_promise.h"
|
||||
|
||||
#define DRV_NAME "sata_promise"
|
||||
#define DRV_VERSION "1.04"
|
||||
#define DRV_VERSION "1.05"
|
||||
|
||||
|
||||
enum {
|
||||
PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */
|
||||
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
|
||||
PDC_TBG_MODE = 0x41, /* TBG mode */
|
||||
PDC_FLASH_CTL = 0x44, /* Flash control register */
|
||||
PDC_PCI_CTL = 0x48, /* PCI control and status register */
|
||||
PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */
|
||||
PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
|
||||
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
|
||||
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
|
||||
PDC_SLEW_CTL = 0x470, /* slew rate control reg */
|
||||
PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */
|
||||
PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */
|
||||
|
||||
PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
|
||||
(1<<8) | (1<<9) | (1<<10),
|
||||
|
|
@ -78,6 +77,9 @@ enum {
|
|||
PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
|
||||
ATA_FLAG_PIO_POLLING,
|
||||
|
||||
/* hp->flags bits */
|
||||
PDC_FLAG_GEN_II = (1 << 0),
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -87,6 +89,7 @@ struct pdc_port_priv {
|
|||
};
|
||||
|
||||
struct pdc_host_priv {
|
||||
unsigned long flags;
|
||||
int hotplug_offset;
|
||||
};
|
||||
|
||||
|
|
@ -235,20 +238,20 @@ static const struct ata_port_info pdc_port_info[] = {
|
|||
|
||||
static const struct pci_device_id pdc_ata_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(PROMISE, 0x3371), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3570), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3571), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3373), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3375), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3376), board_2037x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3570), board_2057x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3571), board_2057x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3574), board_2057x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d73), board_2057x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d75), board_2057x },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d73), board_2037x },
|
||||
|
||||
{ PCI_VDEVICE(PROMISE, 0x3318), board_20319 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3319), board_20319 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3515), board_20319 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3519), board_20319 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d17), board_20319 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d17), board_40518 },
|
||||
{ PCI_VDEVICE(PROMISE, 0x3d18), board_40518 },
|
||||
|
||||
{ PCI_VDEVICE(PROMISE, 0x6629), board_20619 },
|
||||
|
|
@ -277,6 +280,7 @@ static struct pci_driver pdc_ata_pci_driver = {
|
|||
static int pdc_port_start(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->host->dev;
|
||||
struct pdc_host_priv *hp = ap->host->private_data;
|
||||
struct pdc_port_priv *pp;
|
||||
int rc;
|
||||
|
||||
|
|
@ -298,6 +302,16 @@ static int pdc_port_start(struct ata_port *ap)
|
|||
|
||||
ap->private_data = pp;
|
||||
|
||||
/* fix up PHYMODE4 align timing */
|
||||
if ((hp->flags & PDC_FLAG_GEN_II) && sata_scr_valid(ap)) {
|
||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = readl(mmio + 0x014);
|
||||
tmp = (tmp & ~3) | 1; /* set bits 1:0 = 0:1 */
|
||||
writel(tmp, mmio + 0x014);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_kfree:
|
||||
|
|
@ -640,9 +654,11 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
|
|||
* "TODO: figure out why we do this"
|
||||
*/
|
||||
|
||||
/* change FIFO_SHD to 8 dwords, enable BMR_BURST */
|
||||
/* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */
|
||||
tmp = readl(mmio + PDC_FLASH_CTL);
|
||||
tmp |= 0x12000; /* bit 16 (fifo 8 dw) and 13 (bmr burst?) */
|
||||
tmp |= 0x02000; /* bit 13 (enable bmr burst) */
|
||||
if (!(hp->flags & PDC_FLAG_GEN_II))
|
||||
tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */
|
||||
writel(tmp, mmio + PDC_FLASH_CTL);
|
||||
|
||||
/* clear plug/unplug flags for all ports */
|
||||
|
|
@ -653,6 +669,10 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
|
|||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff0000, mmio + hotplug_offset);
|
||||
|
||||
/* don't initialise TBG or SLEW on 2nd generation chips */
|
||||
if (hp->flags & PDC_FLAG_GEN_II)
|
||||
return;
|
||||
|
||||
/* reduce TBG clock to 133 Mhz. */
|
||||
tmp = readl(mmio + PDC_TBG_MODE);
|
||||
tmp &= ~0x30000; /* clear bit 17, 16*/
|
||||
|
|
@ -746,6 +766,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
/* notice 4-port boards */
|
||||
switch (board_idx) {
|
||||
case board_40518:
|
||||
hp->flags |= PDC_FLAG_GEN_II;
|
||||
/* Override hotplug offset for SATAII150 */
|
||||
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
/* Fall through */
|
||||
|
|
@ -759,15 +780,14 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
probe_ent->port[3].scr_addr = base + 0x700;
|
||||
break;
|
||||
case board_2057x:
|
||||
case board_20771:
|
||||
hp->flags |= PDC_FLAG_GEN_II;
|
||||
/* Override hotplug offset for SATAII150 */
|
||||
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
/* Fall through */
|
||||
case board_2037x:
|
||||
probe_ent->n_ports = 2;
|
||||
break;
|
||||
case board_20771:
|
||||
probe_ent->n_ports = 2;
|
||||
break;
|
||||
case board_20619:
|
||||
probe_ent->n_ports = 4;
|
||||
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
|
|||
|
||||
static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
|
||||
{
|
||||
struct ata_eh_info *ehi = &ap->eh_info;
|
||||
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
u8 status;
|
||||
|
||||
|
|
@ -428,6 +429,10 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
|
|||
/* kick HSM in the ass */
|
||||
ata_hsm_move(ap, qc, status, 0);
|
||||
|
||||
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
|
||||
qc->tf.protocol == ATA_PROT_ATAPI_DMA))
|
||||
ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
|
||||
|
||||
return;
|
||||
|
||||
err_hsm:
|
||||
|
|
@ -534,6 +539,7 @@ static void sil_thaw(struct ata_port *ap)
|
|||
*/
|
||||
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
|
||||
{
|
||||
int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
|
||||
unsigned int n, quirks = 0;
|
||||
unsigned char model_num[41];
|
||||
|
||||
|
|
@ -549,16 +555,18 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
|
|||
if (slow_down ||
|
||||
((ap->flags & SIL_FLAG_MOD15WRITE) &&
|
||||
(quirks & SIL_QUIRK_MOD15WRITE))) {
|
||||
ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
|
||||
"(mod15write workaround)\n");
|
||||
if (print_info)
|
||||
ata_dev_printk(dev, KERN_INFO, "applying Seagate "
|
||||
"errata fix (mod15write workaround)\n");
|
||||
dev->max_sectors = 15;
|
||||
return;
|
||||
}
|
||||
|
||||
/* limit to udma5 */
|
||||
if (quirks & SIL_QUIRK_UDMA5MAX) {
|
||||
ata_dev_printk(dev, KERN_INFO,
|
||||
"applying Maxtor errata fix %s\n", model_num);
|
||||
if (print_info)
|
||||
ata_dev_printk(dev, KERN_INFO, "applying Maxtor "
|
||||
"errata fix %s\n", model_num);
|
||||
dev->udma_mask &= ATA_UDMA5;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,10 +100,14 @@ enum {
|
|||
*/
|
||||
PORT_REGS_SIZE = 0x2000,
|
||||
|
||||
PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */
|
||||
PORT_LRAM = 0x0000, /* 31 LRAM slots and PMP regs */
|
||||
PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
|
||||
|
||||
PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
|
||||
PORT_PMP = 0x0f80, /* 8 bytes PMP * 16 (128 bytes) */
|
||||
PORT_PMP_STATUS = 0x0000, /* port device status offset */
|
||||
PORT_PMP_QACTIVE = 0x0004, /* port device QActive offset */
|
||||
PORT_PMP_SIZE = 0x0008, /* 8 bytes per PMP */
|
||||
|
||||
/* 32 bit regs */
|
||||
PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */
|
||||
PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */
|
||||
|
|
@ -126,6 +130,7 @@ enum {
|
|||
PORT_PHY_CFG = 0x1050,
|
||||
PORT_SLOT_STAT = 0x1800,
|
||||
PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
|
||||
PORT_CONTEXT = 0x1e04,
|
||||
PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
|
||||
PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
|
||||
PORT_SCONTROL = 0x1f00,
|
||||
|
|
@ -139,9 +144,9 @@ enum {
|
|||
PORT_CS_INIT = (1 << 2), /* port initialize */
|
||||
PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */
|
||||
PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */
|
||||
PORT_CS_RESUME = (1 << 6), /* port resume */
|
||||
PORT_CS_PMP_RESUME = (1 << 6), /* PMP resume */
|
||||
PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */
|
||||
PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */
|
||||
PORT_CS_PMP_EN = (1 << 13), /* port multiplier enable */
|
||||
PORT_CS_RDY = (1 << 31), /* port ready to accept commands */
|
||||
|
||||
/* PORT_IRQ_STAT/ENABLE_SET/CLR */
|
||||
|
|
@ -562,7 +567,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
|
|||
|
||||
/* do SRST */
|
||||
prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
|
||||
prb->fis[1] = 0; /* no PM yet */
|
||||
prb->fis[1] = 0; /* no PMP yet */
|
||||
|
||||
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
|
||||
writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
|
||||
|
|
@ -1050,7 +1055,8 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
|
|||
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
|
||||
|
||||
/* Clear port multiplier enable and resume bits */
|
||||
writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
|
||||
writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME,
|
||||
port + PORT_CTRL_CLR);
|
||||
}
|
||||
|
||||
/* Turn on interrupts */
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
|
|||
if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
|
||||
pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
|
||||
|
||||
return val|val2;
|
||||
return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */
|
||||
}
|
||||
|
||||
static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
|
||||
|
|
@ -212,7 +212,7 @@ static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
|
|||
if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
|
||||
val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
|
||||
|
||||
return val | val2;
|
||||
return (val | val2) & 0xfffffffb;
|
||||
}
|
||||
|
||||
static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
|
||||
|
|
@ -239,7 +239,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
static int printed_version;
|
||||
struct ata_probe_ent *probe_ent = NULL;
|
||||
int rc;
|
||||
u32 genctl;
|
||||
u32 genctl, val;
|
||||
struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi };
|
||||
int pci_dev_busy = 0;
|
||||
u8 pmr;
|
||||
|
|
@ -285,17 +285,24 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (ent->device != 0x182) {
|
||||
if ((pmr & SIS_PMR_COMBINED) == 0) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"Detected SiS 180/181 chipset in SATA mode\n");
|
||||
"Detected SiS 180/181/964 chipset in SATA mode\n");
|
||||
port2_start = 64;
|
||||
}
|
||||
else {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"Detected SiS 180/181 chipset in combined mode\n");
|
||||
port2_start=0;
|
||||
pi.flags |= ATA_FLAG_SLAVE_POSS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n");
|
||||
pci_read_config_dword ( pdev, 0x6C, &val);
|
||||
if (val & (1L << 31)) {
|
||||
dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n");
|
||||
pi.flags |= ATA_FLAG_SLAVE_POSS;
|
||||
}
|
||||
else
|
||||
dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n");
|
||||
port2_start = 0x20;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/sysdev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/topology.h>
|
||||
#include <linux/device.h>
|
||||
|
|
|
|||
|
|
@ -759,6 +759,8 @@ static struct vio_driver viodasd_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static int need_delete_probe;
|
||||
|
||||
/*
|
||||
* Initialize the whole device driver. Handle module and non-module
|
||||
* versions
|
||||
|
|
@ -773,46 +775,67 @@ static int __init viodasd_init(void)
|
|||
|
||||
if (viopath_hostLp == HvLpIndexInvalid) {
|
||||
printk(VIOD_KERN_WARNING "invalid hosting partition\n");
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto early_fail;
|
||||
}
|
||||
|
||||
printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n",
|
||||
viopath_hostLp);
|
||||
|
||||
/* register the block device */
|
||||
if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) {
|
||||
rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
if (rc) {
|
||||
printk(VIOD_KERN_WARNING
|
||||
"Unable to get major number %d for %s\n",
|
||||
VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
return -EIO;
|
||||
goto early_fail;
|
||||
}
|
||||
/* Actually open the path to the hosting partition */
|
||||
if (viopath_open(viopath_hostLp, viomajorsubtype_blockio,
|
||||
VIOMAXREQ + 2)) {
|
||||
rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio,
|
||||
VIOMAXREQ + 2);
|
||||
if (rc) {
|
||||
printk(VIOD_KERN_WARNING
|
||||
"error opening path to host partition %d\n",
|
||||
viopath_hostLp);
|
||||
unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
return -EIO;
|
||||
goto unregister_blk;
|
||||
}
|
||||
|
||||
/* Initialize our request handler */
|
||||
vio_setHandler(viomajorsubtype_blockio, handle_block_event);
|
||||
|
||||
rc = vio_register_driver(&viodasd_driver);
|
||||
if (rc == 0)
|
||||
driver_create_file(&viodasd_driver.driver, &driver_attr_probe);
|
||||
if (rc) {
|
||||
printk(VIOD_KERN_WARNING "vio_register_driver failed\n");
|
||||
goto unset_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this call fails, it just means that we cannot dynamically
|
||||
* add virtual disks, but the driver will still work fine for
|
||||
* all existing disk, so ignore the failure.
|
||||
*/
|
||||
if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe))
|
||||
need_delete_probe = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
unset_handler:
|
||||
vio_clearHandler(viomajorsubtype_blockio);
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
|
||||
unregister_blk:
|
||||
unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
early_fail:
|
||||
return rc;
|
||||
}
|
||||
module_init(viodasd_init);
|
||||
|
||||
void viodasd_exit(void)
|
||||
void __exit viodasd_exit(void)
|
||||
{
|
||||
driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
|
||||
if (need_delete_probe)
|
||||
driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
|
||||
vio_unregister_driver(&viodasd_driver);
|
||||
vio_clearHandler(viomajorsubtype_blockio);
|
||||
unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
|
||||
unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
|
||||
}
|
||||
|
||||
module_exit(viodasd_exit);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/fcntl.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
etc voltage & frequency control is not supported!
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include <linux/ide.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
#include <asm/processor.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -442,7 +442,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
|
|||
hwif->speedproc = &via_set_drive;
|
||||
|
||||
|
||||
#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
|
||||
hwif->irq = hwif->channel ? 15 : 14;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
*/
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include "isdn_divert.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
|
|
|
|||
|
|
@ -228,4 +228,11 @@ config ANSLCD
|
|||
tristate "Support for ANS LCD display"
|
||||
depends on ADB_CUDA && PPC_PMAC
|
||||
|
||||
config PMAC_RACKMETER
|
||||
tristate "Support for Apple XServe front panel LEDs"
|
||||
depends on PPC_PMAC
|
||||
help
|
||||
This driver procides some support to control the front panel
|
||||
blue LEDs "vu-meter" of the XServer macs.
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -42,3 +42,4 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
|
|||
windfarm_smu_sensors.o \
|
||||
windfarm_max6690_sensor.o \
|
||||
windfarm_lm75_sensor.o windfarm_pid.o
|
||||
obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
|
||||
|
|
|
|||
612
drivers/macintosh/rack-meter.c
Normal file
612
drivers/macintosh/rack-meter.c
Normal file
|
|
@ -0,0 +1,612 @@
|
|||
/*
|
||||
* RackMac vu-meter driver
|
||||
*
|
||||
* (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
|
||||
* <benh@kernel.crashing.org>
|
||||
*
|
||||
* Released under the term of the GNU GPL v2.
|
||||
*
|
||||
* Support the CPU-meter LEDs of the Xserve G5
|
||||
*
|
||||
* TODO: Implement PWM to do variable intensity and provide userland
|
||||
* interface for fun. Also, the CPU-meter could be made nicer by being
|
||||
* a bit less "immediate" but giving instead a more average load over
|
||||
* time. Patches welcome :-)
|
||||
*
|
||||
*/
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/dbdma.h>
|
||||
#include <asm/dbdma.h>
|
||||
#include <asm/macio.h>
|
||||
#include <asm/keylargo.h>
|
||||
|
||||
/* Number of samples in a sample buffer */
|
||||
#define SAMPLE_COUNT 256
|
||||
|
||||
/* CPU meter sampling rate in ms */
|
||||
#define CPU_SAMPLING_RATE 250
|
||||
|
||||
struct rackmeter_dma {
|
||||
struct dbdma_cmd cmd[4] ____cacheline_aligned;
|
||||
u32 mark ____cacheline_aligned;
|
||||
u32 buf1[SAMPLE_COUNT] ____cacheline_aligned;
|
||||
u32 buf2[SAMPLE_COUNT] ____cacheline_aligned;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct rackmeter_cpu {
|
||||
struct work_struct sniffer;
|
||||
cputime64_t prev_wall;
|
||||
cputime64_t prev_idle;
|
||||
int zero;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct rackmeter {
|
||||
struct macio_dev *mdev;
|
||||
unsigned int irq;
|
||||
struct device_node *i2s;
|
||||
u8 *ubuf;
|
||||
struct dbdma_regs __iomem *dma_regs;
|
||||
void __iomem *i2s_regs;
|
||||
dma_addr_t dma_buf_p;
|
||||
struct rackmeter_dma *dma_buf_v;
|
||||
int stale_irq;
|
||||
struct rackmeter_cpu cpu[2];
|
||||
int paused;
|
||||
struct mutex sem;
|
||||
};
|
||||
|
||||
/* To be set as a tunable */
|
||||
static int rackmeter_ignore_nice;
|
||||
|
||||
/* This GPIO is whacked by the OS X driver when initializing */
|
||||
#define RACKMETER_MAGIC_GPIO 0x78
|
||||
|
||||
/* This is copied from cpufreq_ondemand, maybe we should put it in
|
||||
* a common header somewhere
|
||||
*/
|
||||
static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
|
||||
{
|
||||
cputime64_t retval;
|
||||
|
||||
retval = cputime64_add(kstat_cpu(cpu).cpustat.idle,
|
||||
kstat_cpu(cpu).cpustat.iowait);
|
||||
|
||||
if (rackmeter_ignore_nice)
|
||||
retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void rackmeter_setup_i2s(struct rackmeter *rm)
|
||||
{
|
||||
struct macio_chip *macio = rm->mdev->bus->chip;
|
||||
|
||||
/* First whack magic GPIO */
|
||||
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, RACKMETER_MAGIC_GPIO, 5);
|
||||
|
||||
|
||||
/* Call feature code to enable the sound channel and the proper
|
||||
* clock sources
|
||||
*/
|
||||
pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, rm->i2s, 0, 1);
|
||||
|
||||
/* Power i2s and stop i2s clock. We whack MacIO FCRs directly for now.
|
||||
* This is a bit racy, thus we should add new platform functions to
|
||||
* handle that. snd-aoa needs that too
|
||||
*/
|
||||
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
|
||||
MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
|
||||
(void)MACIO_IN32(KEYLARGO_FCR1);
|
||||
udelay(10);
|
||||
|
||||
/* Then setup i2s. For now, we use the same magic value that
|
||||
* the OS X driver seems to use. We might want to play around
|
||||
* with the clock divisors later
|
||||
*/
|
||||
out_le32(rm->i2s_regs + 0x10, 0x01fa0000);
|
||||
(void)in_le32(rm->i2s_regs + 0x10);
|
||||
udelay(10);
|
||||
|
||||
/* Fully restart i2s*/
|
||||
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE |
|
||||
KL1_I2S0_CLK_ENABLE_BIT);
|
||||
(void)MACIO_IN32(KEYLARGO_FCR1);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void rackmeter_set_default_pattern(struct rackmeter *rm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i < 8)
|
||||
rm->ubuf[i] = (i & 1) * 255;
|
||||
else
|
||||
rm->ubuf[i] = ((~i) & 1) * 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void rackmeter_do_pause(struct rackmeter *rm, int pause)
|
||||
{
|
||||
struct rackmeter_dma *rdma = rm->dma_buf_v;
|
||||
|
||||
pr_debug("rackmeter: %s\n", pause ? "paused" : "started");
|
||||
|
||||
rm->paused = pause;
|
||||
if (pause) {
|
||||
DBDMA_DO_STOP(rm->dma_regs);
|
||||
return;
|
||||
}
|
||||
memset(rdma->buf1, 0, SAMPLE_COUNT & sizeof(u32));
|
||||
memset(rdma->buf2, 0, SAMPLE_COUNT & sizeof(u32));
|
||||
|
||||
rm->dma_buf_v->mark = 0;
|
||||
|
||||
mb();
|
||||
out_le32(&rm->dma_regs->cmdptr_hi, 0);
|
||||
out_le32(&rm->dma_regs->cmdptr, rm->dma_buf_p);
|
||||
out_le32(&rm->dma_regs->control, (RUN << 16) | RUN);
|
||||
}
|
||||
|
||||
static void rackmeter_setup_dbdma(struct rackmeter *rm)
|
||||
{
|
||||
struct rackmeter_dma *db = rm->dma_buf_v;
|
||||
struct dbdma_cmd *cmd = db->cmd;
|
||||
|
||||
/* Make sure dbdma is reset */
|
||||
DBDMA_DO_RESET(rm->dma_regs);
|
||||
|
||||
pr_debug("rackmeter: mark offset=0x%lx\n",
|
||||
offsetof(struct rackmeter_dma, mark));
|
||||
pr_debug("rackmeter: buf1 offset=0x%lx\n",
|
||||
offsetof(struct rackmeter_dma, buf1));
|
||||
pr_debug("rackmeter: buf2 offset=0x%lx\n",
|
||||
offsetof(struct rackmeter_dma, buf2));
|
||||
|
||||
/* Prepare 4 dbdma commands for the 2 buffers */
|
||||
memset(cmd, 0, 4 * sizeof(struct dbdma_cmd));
|
||||
st_le16(&cmd->req_count, 4);
|
||||
st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
|
||||
st_le32(&cmd->phy_addr, rm->dma_buf_p +
|
||||
offsetof(struct rackmeter_dma, mark));
|
||||
st_le32(&cmd->cmd_dep, 0x02000000);
|
||||
cmd++;
|
||||
|
||||
st_le16(&cmd->req_count, SAMPLE_COUNT * 4);
|
||||
st_le16(&cmd->command, OUTPUT_MORE);
|
||||
st_le32(&cmd->phy_addr, rm->dma_buf_p +
|
||||
offsetof(struct rackmeter_dma, buf1));
|
||||
cmd++;
|
||||
|
||||
st_le16(&cmd->req_count, 4);
|
||||
st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
|
||||
st_le32(&cmd->phy_addr, rm->dma_buf_p +
|
||||
offsetof(struct rackmeter_dma, mark));
|
||||
st_le32(&cmd->cmd_dep, 0x01000000);
|
||||
cmd++;
|
||||
|
||||
st_le16(&cmd->req_count, SAMPLE_COUNT * 4);
|
||||
st_le16(&cmd->command, OUTPUT_MORE | BR_ALWAYS);
|
||||
st_le32(&cmd->phy_addr, rm->dma_buf_p +
|
||||
offsetof(struct rackmeter_dma, buf2));
|
||||
st_le32(&cmd->cmd_dep, rm->dma_buf_p);
|
||||
|
||||
rackmeter_do_pause(rm, 0);
|
||||
}
|
||||
|
||||
static void rackmeter_do_timer(void *data)
|
||||
{
|
||||
struct rackmeter *rm = data;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct rackmeter_cpu *rcpu = &rm->cpu[cpu];
|
||||
cputime64_t cur_jiffies, total_idle_ticks;
|
||||
unsigned int total_ticks, idle_ticks;
|
||||
int i, offset, load, cumm, pause;
|
||||
|
||||
cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
|
||||
total_ticks = (unsigned int)cputime64_sub(cur_jiffies,
|
||||
rcpu->prev_wall);
|
||||
rcpu->prev_wall = cur_jiffies;
|
||||
|
||||
total_idle_ticks = get_cpu_idle_time(cpu);
|
||||
idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks,
|
||||
rcpu->prev_idle);
|
||||
rcpu->prev_idle = total_idle_ticks;
|
||||
|
||||
/* We do a very dumb calculation to update the LEDs for now,
|
||||
* we'll do better once we have actual PWM implemented
|
||||
*/
|
||||
load = (9 * (total_ticks - idle_ticks)) / total_ticks;
|
||||
|
||||
offset = cpu << 3;
|
||||
cumm = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
u8 ub = (load > i) ? 0xff : 0;
|
||||
rm->ubuf[i + offset] = ub;
|
||||
cumm |= ub;
|
||||
}
|
||||
rcpu->zero = (cumm == 0);
|
||||
|
||||
/* Now check if LEDs are all 0, we can stop DMA */
|
||||
pause = (rm->cpu[0].zero && rm->cpu[1].zero);
|
||||
if (pause != rm->paused) {
|
||||
mutex_lock(&rm->sem);
|
||||
pause = (rm->cpu[0].zero && rm->cpu[1].zero);
|
||||
rackmeter_do_pause(rm, pause);
|
||||
mutex_unlock(&rm->sem);
|
||||
}
|
||||
schedule_delayed_work_on(cpu, &rcpu->sniffer,
|
||||
msecs_to_jiffies(CPU_SAMPLING_RATE));
|
||||
}
|
||||
|
||||
static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
/* This driver works only with 1 or 2 CPUs numbered 0 and 1,
|
||||
* but that's really all we have on Apple Xserve. It doesn't
|
||||
* play very nice with CPU hotplug neither but we don't do that
|
||||
* on those machines yet
|
||||
*/
|
||||
|
||||
INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm);
|
||||
INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm);
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
struct rackmeter_cpu *rcpu;
|
||||
|
||||
if (cpu > 1)
|
||||
continue;
|
||||
rcpu = &rm->cpu[cpu];;
|
||||
rcpu->prev_idle = get_cpu_idle_time(cpu);
|
||||
rcpu->prev_wall = jiffies64_to_cputime64(get_jiffies_64());
|
||||
schedule_delayed_work_on(cpu, &rm->cpu[cpu].sniffer,
|
||||
msecs_to_jiffies(CPU_SAMPLING_RATE));
|
||||
}
|
||||
}
|
||||
|
||||
static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
|
||||
{
|
||||
cancel_rearming_delayed_work(&rm->cpu[0].sniffer);
|
||||
cancel_rearming_delayed_work(&rm->cpu[1].sniffer);
|
||||
}
|
||||
|
||||
static int rackmeter_setup(struct rackmeter *rm)
|
||||
{
|
||||
pr_debug("rackmeter: setting up i2s..\n");
|
||||
rackmeter_setup_i2s(rm);
|
||||
|
||||
pr_debug("rackmeter: setting up default pattern..\n");
|
||||
rackmeter_set_default_pattern(rm);
|
||||
|
||||
pr_debug("rackmeter: setting up dbdma..\n");
|
||||
rackmeter_setup_dbdma(rm);
|
||||
|
||||
pr_debug("rackmeter: start CPU measurements..\n");
|
||||
rackmeter_init_cpu_sniffer(rm);
|
||||
|
||||
printk(KERN_INFO "RackMeter initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX FIXME: No PWM yet, this is 0/1 */
|
||||
static u32 rackmeter_calc_sample(struct rackmeter *rm, unsigned int index)
|
||||
{
|
||||
int led;
|
||||
u32 sample = 0;
|
||||
|
||||
for (led = 0; led < 16; led++) {
|
||||
sample >>= 1;
|
||||
sample |= ((rm->ubuf[led] >= 0x80) << 15);
|
||||
}
|
||||
return (sample << 17) | (sample >> 15);
|
||||
}
|
||||
|
||||
static irqreturn_t rackmeter_irq(int irq, void *arg)
|
||||
{
|
||||
struct rackmeter *rm = arg;
|
||||
struct rackmeter_dma *db = rm->dma_buf_v;
|
||||
unsigned int mark, i;
|
||||
u32 *buf;
|
||||
|
||||
/* Flush PCI buffers with an MMIO read. Maybe we could actually
|
||||
* check the status one day ... in case things go wrong, though
|
||||
* this never happened to me
|
||||
*/
|
||||
(void)in_le32(&rm->dma_regs->status);
|
||||
|
||||
/* Make sure the CPU gets us in order */
|
||||
rmb();
|
||||
|
||||
/* Read mark */
|
||||
mark = db->mark;
|
||||
if (mark != 1 && mark != 2) {
|
||||
printk(KERN_WARNING "rackmeter: Incorrect DMA mark 0x%08x\n",
|
||||
mark);
|
||||
/* We allow for 3 errors like that (stale DBDMA irqs) */
|
||||
if (++rm->stale_irq > 3) {
|
||||
printk(KERN_ERR "rackmeter: Too many errors,"
|
||||
" stopping DMA\n");
|
||||
DBDMA_DO_RESET(rm->dma_regs);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Next buffer we need to fill is mark value */
|
||||
buf = mark == 1 ? db->buf1 : db->buf2;
|
||||
|
||||
/* Fill it now. This routine converts the 8 bits depth sample array
|
||||
* into the PWM bitmap for each LED.
|
||||
*/
|
||||
for (i = 0; i < SAMPLE_COUNT; i++)
|
||||
buf[i] = rackmeter_calc_sample(rm, i);
|
||||
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit rackmeter_probe(struct macio_dev* mdev,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *i2s = NULL, *np = NULL;
|
||||
struct rackmeter *rm = NULL;
|
||||
struct resource ri2s, rdma;
|
||||
int rc = -ENODEV;
|
||||
|
||||
pr_debug("rackmeter_probe()\n");
|
||||
|
||||
/* Get i2s-a node */
|
||||
while ((i2s = of_get_next_child(mdev->ofdev.node, i2s)) != NULL)
|
||||
if (strcmp(i2s->name, "i2s-a") == 0)
|
||||
break;
|
||||
if (i2s == NULL) {
|
||||
pr_debug(" i2s-a child not found\n");
|
||||
goto bail;
|
||||
}
|
||||
/* Get lightshow or virtual sound */
|
||||
while ((np = of_get_next_child(i2s, np)) != NULL) {
|
||||
if (strcmp(np->name, "lightshow") == 0)
|
||||
break;
|
||||
if ((strcmp(np->name, "sound") == 0) &&
|
||||
get_property(np, "virtual", NULL) != NULL)
|
||||
break;
|
||||
}
|
||||
if (np == NULL) {
|
||||
pr_debug(" lightshow or sound+virtual child not found\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Create and initialize our instance data */
|
||||
rm = kzalloc(sizeof(struct rackmeter), GFP_KERNEL);
|
||||
if (rm == NULL) {
|
||||
printk(KERN_ERR "rackmeter: failed to allocate memory !\n");
|
||||
rc = -ENOMEM;
|
||||
goto bail_release;
|
||||
}
|
||||
rm->mdev = mdev;
|
||||
rm->i2s = i2s;
|
||||
mutex_init(&rm->sem);
|
||||
dev_set_drvdata(&mdev->ofdev.dev, rm);
|
||||
/* Check resources availability. We need at least resource 0 and 1 */
|
||||
#if 0 /* Use that when i2s-a is finally an mdev per-se */
|
||||
if (macio_resource_count(mdev) < 2 || macio_irq_count(mdev) < 2) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: found match but lacks resources: %s"
|
||||
" (%d resources, %d interrupts)\n",
|
||||
mdev->ofdev.node->full_name);
|
||||
rc = -ENXIO;
|
||||
goto bail_free;
|
||||
}
|
||||
if (macio_request_resources(mdev, "rackmeter")) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to request resources: %s\n",
|
||||
mdev->ofdev.node->full_name);
|
||||
rc = -EBUSY;
|
||||
goto bail_free;
|
||||
}
|
||||
rm->irq = macio_irq(mdev, 1);
|
||||
#else
|
||||
rm->irq = irq_of_parse_and_map(i2s, 1);
|
||||
if (rm->irq == NO_IRQ ||
|
||||
of_address_to_resource(i2s, 0, &ri2s) ||
|
||||
of_address_to_resource(i2s, 1, &rdma)) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: found match but lacks resources: %s",
|
||||
mdev->ofdev.node->full_name);
|
||||
rc = -ENXIO;
|
||||
goto bail_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
pr_debug(" i2s @0x%08x\n", (unsigned int)ri2s.start);
|
||||
pr_debug(" dma @0x%08x\n", (unsigned int)rdma.start);
|
||||
pr_debug(" irq %d\n", rm->irq);
|
||||
|
||||
rm->ubuf = (u8 *)__get_free_page(GFP_KERNEL);
|
||||
if (rm->ubuf == NULL) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to allocate samples page !\n");
|
||||
rc = -ENOMEM;
|
||||
goto bail_release;
|
||||
}
|
||||
|
||||
rm->dma_buf_v = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
|
||||
sizeof(struct rackmeter_dma),
|
||||
&rm->dma_buf_p, GFP_KERNEL);
|
||||
if (rm->dma_buf_v == NULL) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to allocate dma buffer !\n");
|
||||
rc = -ENOMEM;
|
||||
goto bail_free_samples;
|
||||
}
|
||||
#if 0
|
||||
rm->i2s_regs = ioremap(macio_resource_start(mdev, 0), 0x1000);
|
||||
#else
|
||||
rm->i2s_regs = ioremap(ri2s.start, 0x1000);
|
||||
#endif
|
||||
if (rm->i2s_regs == NULL) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to map i2s registers !\n");
|
||||
rc = -ENXIO;
|
||||
goto bail_free_dma;
|
||||
}
|
||||
#if 0
|
||||
rm->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x100);
|
||||
#else
|
||||
rm->dma_regs = ioremap(rdma.start, 0x100);
|
||||
#endif
|
||||
if (rm->dma_regs == NULL) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to map dma registers !\n");
|
||||
rc = -ENXIO;
|
||||
goto bail_unmap_i2s;
|
||||
}
|
||||
|
||||
rc = rackmeter_setup(rm);
|
||||
if (rc) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to initialize !\n");
|
||||
rc = -ENXIO;
|
||||
goto bail_unmap_dma;
|
||||
}
|
||||
|
||||
rc = request_irq(rm->irq, rackmeter_irq, 0, "rackmeter", rm);
|
||||
if (rc != 0) {
|
||||
printk(KERN_ERR
|
||||
"rackmeter: failed to request interrupt !\n");
|
||||
goto bail_stop_dma;
|
||||
}
|
||||
of_node_put(np);
|
||||
return 0;
|
||||
|
||||
bail_stop_dma:
|
||||
DBDMA_DO_RESET(rm->dma_regs);
|
||||
bail_unmap_dma:
|
||||
iounmap(rm->dma_regs);
|
||||
bail_unmap_i2s:
|
||||
iounmap(rm->i2s_regs);
|
||||
bail_free_dma:
|
||||
dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
|
||||
sizeof(struct rackmeter_dma),
|
||||
rm->dma_buf_v, rm->dma_buf_p);
|
||||
bail_free_samples:
|
||||
free_page((unsigned long)rm->ubuf);
|
||||
bail_release:
|
||||
#if 0
|
||||
macio_release_resources(mdev);
|
||||
#endif
|
||||
bail_free:
|
||||
kfree(rm);
|
||||
bail:
|
||||
of_node_put(i2s);
|
||||
of_node_put(np);
|
||||
dev_set_drvdata(&mdev->ofdev.dev, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit rackmeter_remove(struct macio_dev* mdev)
|
||||
{
|
||||
struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
|
||||
|
||||
/* Stop CPU sniffer timer & work queues */
|
||||
rackmeter_stop_cpu_sniffer(rm);
|
||||
|
||||
/* Clear reference to private data */
|
||||
dev_set_drvdata(&mdev->ofdev.dev, NULL);
|
||||
|
||||
/* Stop/reset dbdma */
|
||||
DBDMA_DO_RESET(rm->dma_regs);
|
||||
|
||||
/* Release the IRQ */
|
||||
free_irq(rm->irq, rm);
|
||||
|
||||
/* Unmap registers */
|
||||
iounmap(rm->dma_regs);
|
||||
iounmap(rm->i2s_regs);
|
||||
|
||||
/* Free DMA */
|
||||
dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
|
||||
sizeof(struct rackmeter_dma),
|
||||
rm->dma_buf_v, rm->dma_buf_p);
|
||||
|
||||
/* Free samples */
|
||||
free_page((unsigned long)rm->ubuf);
|
||||
|
||||
#if 0
|
||||
/* Release resources */
|
||||
macio_release_resources(mdev);
|
||||
#endif
|
||||
|
||||
/* Get rid of me */
|
||||
kfree(rm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rackmeter_shutdown(struct macio_dev* mdev)
|
||||
{
|
||||
struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
|
||||
|
||||
if (rm == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
/* Stop CPU sniffer timer & work queues */
|
||||
rackmeter_stop_cpu_sniffer(rm);
|
||||
|
||||
/* Stop/reset dbdma */
|
||||
DBDMA_DO_RESET(rm->dma_regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id rackmeter_match[] = {
|
||||
{ .name = "i2s" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct macio_driver rackmeter_drv = {
|
||||
.name = "rackmeter",
|
||||
.owner = THIS_MODULE,
|
||||
.match_table = rackmeter_match,
|
||||
.probe = rackmeter_probe,
|
||||
.remove = rackmeter_remove,
|
||||
.shutdown = rackmeter_shutdown,
|
||||
};
|
||||
|
||||
|
||||
static int __init rackmeter_init(void)
|
||||
{
|
||||
pr_debug("rackmeter_init()\n");
|
||||
|
||||
return macio_register_driver(&rackmeter_drv);
|
||||
}
|
||||
|
||||
static void __exit rackmeter_exit(void)
|
||||
{
|
||||
pr_debug("rackmeter_exit()\n");
|
||||
|
||||
macio_unregister_driver(&rackmeter_drv);
|
||||
}
|
||||
|
||||
module_init(rackmeter_init);
|
||||
module_exit(rackmeter_exit);
|
||||
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Benjamin Herrenschmidt <[email protected]>");
|
||||
MODULE_DESCRIPTION("RackMeter: Support vu-meter on XServe front panel");
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
#include <asm/abs_addr.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <asm/of_platform.h>
|
||||
|
||||
#define VERSION "0.7"
|
||||
#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
|
||||
|
|
@ -653,7 +654,7 @@ static int __init smu_init_sysfs(void)
|
|||
* I'm a bit too far from figuring out how that works with those
|
||||
* new chipsets, but that will come back and bite us
|
||||
*/
|
||||
of_register_driver(&smu_of_platform_driver);
|
||||
of_register_platform_driver(&smu_of_platform_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <asm/of_platform.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@
|
|||
#include <asm/sections.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <asm/macio.h>
|
||||
#include <asm/of_platform.h>
|
||||
|
||||
#include "therm_pm72.h"
|
||||
|
||||
|
|
@ -2236,14 +2237,14 @@ static int __init therm_pm72_init(void)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
of_register_driver(&fcu_of_platform_driver);
|
||||
of_register_platform_driver(&fcu_of_platform_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit therm_pm72_exit(void)
|
||||
{
|
||||
of_unregister_driver(&fcu_of_platform_driver);
|
||||
of_unregister_platform_driver(&fcu_of_platform_driver);
|
||||
|
||||
if (of_dev)
|
||||
of_device_unregister(of_dev);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,13 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <asm/of_platform.h>
|
||||
#include <asm/macio.h>
|
||||
|
||||
#define LOG_TEMP 0 /* continously log temperature */
|
||||
|
|
@ -511,14 +512,14 @@ g4fan_init( void )
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
of_register_driver( &therm_of_driver );
|
||||
of_register_platform_driver( &therm_of_driver );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
g4fan_exit( void )
|
||||
{
|
||||
of_unregister_driver( &therm_of_driver );
|
||||
of_unregister_platform_driver( &therm_of_driver );
|
||||
|
||||
if( x.of_dev )
|
||||
of_device_unregister( x.of_dev );
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
#include "dvb_demux.h"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include "ehea.h"
|
||||
#include "ehea_phyp.h"
|
||||
#include "ehea_qmr.h"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dcr.h>
|
||||
|
||||
/*
|
||||
* These MAL "versions" probably aren't the real versions IBM uses for these
|
||||
|
|
@ -191,6 +192,7 @@ struct mal_commac {
|
|||
|
||||
struct ibm_ocp_mal {
|
||||
int dcrbase;
|
||||
dcr_host_t dcrhost;
|
||||
|
||||
struct list_head poll_list;
|
||||
struct net_device poll_dev;
|
||||
|
|
@ -207,12 +209,12 @@ struct ibm_ocp_mal {
|
|||
|
||||
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
|
||||
{
|
||||
return mfdcr(mal->dcrbase + reg);
|
||||
return dcr_read(mal->dcrhost, mal->dcrbase + reg);
|
||||
}
|
||||
|
||||
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
|
||||
{
|
||||
mtdcr(mal->dcrbase + reg, val);
|
||||
dcr_write(mal->dcrhost, mal->dcrbase + reg, val);
|
||||
}
|
||||
|
||||
/* Register MAL devices */
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
#include <asm/semaphore.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
|
@ -1000,8 +999,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
|
|||
adapter->mac_addr = 0;
|
||||
memcpy(&adapter->mac_addr, mac_addr_p, 6);
|
||||
|
||||
adapter->liobn = dev->iommu_table->it_index;
|
||||
|
||||
netdev->irq = dev->irq;
|
||||
netdev->open = ibmveth_open;
|
||||
netdev->poll = ibmveth_poll;
|
||||
|
|
@ -1115,7 +1112,6 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
|
|||
seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
|
||||
|
||||
seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address);
|
||||
seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn);
|
||||
seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
current_mac[0], current_mac[1], current_mac[2],
|
||||
current_mac[3], current_mac[4], current_mac[5]);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ struct ibmveth_adapter {
|
|||
struct net_device_stats stats;
|
||||
unsigned int mcastFilterSize;
|
||||
unsigned long mac_addr;
|
||||
unsigned long liobn;
|
||||
void * buffer_list_addr;
|
||||
void * filter_list_addr;
|
||||
dma_addr_t buffer_list_dma;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ static const char version[] = "lance.c:v1.16 2006/11/09 [email protected], becker@c
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
|
|||
goto device_create_fail;
|
||||
}
|
||||
|
||||
phydev->irq = -1;
|
||||
phydev->irq = PHY_IGNORE_INTERRUPT;
|
||||
phydev->dev.bus = &mdio_bus_type;
|
||||
|
||||
if(number)
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "h/skdrv1st.h"
|
||||
#include "h/skdrv2nd.h"
|
||||
|
|
|
|||
|
|
@ -88,12 +88,11 @@ MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);
|
|||
static inline u32
|
||||
spider_net_read_reg(struct spider_net_card *card, u32 reg)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = readl(card->regs + reg);
|
||||
value = le32_to_cpu(value);
|
||||
|
||||
return value;
|
||||
/* We use the powerpc specific variants instead of readl_be() because
|
||||
* we know spidernet is not a real PCI device and we can thus avoid the
|
||||
* performance hit caused by the PCI workarounds.
|
||||
*/
|
||||
return in_be32(card->regs + reg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -105,8 +104,11 @@ spider_net_read_reg(struct spider_net_card *card, u32 reg)
|
|||
static inline void
|
||||
spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
|
||||
{
|
||||
value = cpu_to_le32(value);
|
||||
writel(value, card->regs + reg);
|
||||
/* We use the powerpc specific variants instead of writel_be() because
|
||||
* we know spidernet is not a real PCI device and we can thus avoid the
|
||||
* performance hit caused by the PCI workarounds.
|
||||
*/
|
||||
out_be32(card->regs + reg, value);
|
||||
}
|
||||
|
||||
/** spider_net_write_phy - write to phy register
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <linux/ethtool.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/processor.h> /* Processor type for cache alignment. */
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey ([email protected]
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include <linux/if_vlan.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
|
|
@ -3012,6 +3013,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
|
|||
#endif
|
||||
|
||||
err = -ENODEV;
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
goto err_out;
|
||||
pci_set_master(pdev);
|
||||
|
||||
if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) {
|
||||
qp = quattro_pci_find(pdev);
|
||||
if (qp == NULL)
|
||||
|
|
|
|||
|
|
@ -1826,7 +1826,7 @@ static void tr_rx(struct net_device *dev)
|
|||
skb->protocol = tr_type_trans(skb, dev);
|
||||
if (IPv4_p) {
|
||||
skb->csum = chksum;
|
||||
skb->ip_summed = 1;
|
||||
skb->ip_summed = CHECKSUM_COMPLETE;
|
||||
}
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
|
|
|
|||
|
|
@ -473,9 +473,9 @@
|
|||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/uaccess.h>
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
#include <asm/machdep.h>
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
||||
#include "de4x5.h"
|
||||
|
||||
|
|
@ -4151,7 +4151,7 @@ get_hw_addr(struct net_device *dev)
|
|||
/* If possible, try to fix a broken card - SMC only so far */
|
||||
srom_repair(dev, broken);
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
/*
|
||||
** If the address starts with 00 a0, we have to bit-reverse
|
||||
** each byte of the address.
|
||||
|
|
@ -4168,7 +4168,7 @@ get_hw_addr(struct net_device *dev)
|
|||
dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
||||
/* Test for a bad enet address */
|
||||
status = test_bad_enet(dev, status);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ static const int multicast_filter_limit = 32;
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ethtool.h>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
|
|
|
|||
1
drivers/ps3/Makefile
Normal file
1
drivers/ps3/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
obj-y += system-bus.o
|
||||
362
drivers/ps3/system-bus.c
Normal file
362
drivers/ps3/system-bus.c
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* PS3 system bus driver.
|
||||
*
|
||||
* Copyright (C) 2006 Sony Computer Entertainment Inc.
|
||||
* Copyright 2006 Sony Corp.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/ps3.h>
|
||||
#include <asm/lv1call.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
|
||||
static void _dump_mmio_region(const struct ps3_mmio_region* r,
|
||||
const char* func, int line)
|
||||
{
|
||||
pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id,
|
||||
r->did.dev_id);
|
||||
pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
|
||||
pr_debug("%s:%d: len %lxh\n", func, line, r->len);
|
||||
pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);
|
||||
}
|
||||
|
||||
int ps3_mmio_region_create(struct ps3_mmio_region *r)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id,
|
||||
r->bus_addr, r->len, r->page_size, &r->lpar_addr);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n",
|
||||
__func__, __LINE__, ps3_result(result));
|
||||
r->lpar_addr = r->len = r->bus_addr = 0;
|
||||
}
|
||||
|
||||
dump_mmio_region(r);
|
||||
return result;
|
||||
}
|
||||
|
||||
int ps3_free_mmio_region(struct ps3_mmio_region *r)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id,
|
||||
r->bus_addr);
|
||||
|
||||
if (result)
|
||||
pr_debug("%s:%d: lv1_unmap_device_mmio_region failed: %s\n",
|
||||
__func__, __LINE__, ps3_result(result));
|
||||
|
||||
r->lpar_addr = r->len = r->bus_addr = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ps3_system_bus_match(struct device *_dev,
|
||||
struct device_driver *_drv)
|
||||
{
|
||||
int result;
|
||||
struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv);
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
|
||||
result = dev->match_id == drv->match_id;
|
||||
|
||||
pr_info("%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, __LINE__,
|
||||
dev->match_id, dev->core.bus_id, drv->match_id, drv->core.name,
|
||||
(result ? "match" : "miss"));
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ps3_system_bus_probe(struct device *_dev)
|
||||
{
|
||||
int result;
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
struct ps3_system_bus_driver *drv =
|
||||
to_ps3_system_bus_driver(_dev->driver);
|
||||
|
||||
result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: lv1_open_device failed (%d)\n",
|
||||
__func__, __LINE__, result);
|
||||
result = -EACCES;
|
||||
goto clean_none;
|
||||
}
|
||||
|
||||
if (dev->d_region->did.bus_id) {
|
||||
result = ps3_dma_region_create(dev->d_region);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n",
|
||||
__func__, __LINE__, result);
|
||||
BUG_ON("check region type");
|
||||
result = -EINVAL;
|
||||
goto clean_device;
|
||||
}
|
||||
}
|
||||
|
||||
BUG_ON(!drv);
|
||||
|
||||
if (drv->probe)
|
||||
result = drv->probe(dev);
|
||||
else
|
||||
pr_info("%s:%d: %s no probe method\n", __func__, __LINE__,
|
||||
dev->core.bus_id);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__);
|
||||
goto clean_dma;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
clean_dma:
|
||||
ps3_dma_region_free(dev->d_region);
|
||||
clean_device:
|
||||
lv1_close_device(dev->did.bus_id, dev->did.dev_id);
|
||||
clean_none:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ps3_system_bus_remove(struct device *_dev)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
struct ps3_system_bus_driver *drv =
|
||||
to_ps3_system_bus_driver(_dev->driver);
|
||||
|
||||
if (drv->remove)
|
||||
drv->remove(dev);
|
||||
else
|
||||
pr_info("%s:%d: %s no remove method\n", __func__, __LINE__,
|
||||
dev->core.bus_id);
|
||||
|
||||
ps3_dma_region_free(dev->d_region);
|
||||
ps3_free_mmio_region(dev->m_region);
|
||||
lv1_close_device(dev->did.bus_id, dev->did.dev_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bus_type ps3_system_bus_type = {
|
||||
.name = "ps3_system_bus",
|
||||
.match = ps3_system_bus_match,
|
||||
.probe = ps3_system_bus_probe,
|
||||
.remove = ps3_system_bus_remove,
|
||||
};
|
||||
|
||||
int __init ps3_system_bus_init(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
|
||||
return 0;
|
||||
|
||||
result = bus_register(&ps3_system_bus_type);
|
||||
BUG_ON(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
core_initcall(ps3_system_bus_init);
|
||||
|
||||
/* Allocates a contiguous real buffer and creates mappings over it.
|
||||
* Returns the virtual address of the buffer and sets dma_handle
|
||||
* to the dma address (mapping) of the first page.
|
||||
*/
|
||||
|
||||
static void * ps3_alloc_coherent(struct device *_dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
int result;
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
unsigned long virt_addr;
|
||||
|
||||
BUG_ON(!dev->d_region->bus_addr);
|
||||
|
||||
flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
|
||||
flag |= __GFP_ZERO;
|
||||
|
||||
virt_addr = __get_free_pages(flag, get_order(size));
|
||||
|
||||
if (!virt_addr) {
|
||||
pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__);
|
||||
goto clean_none;
|
||||
}
|
||||
|
||||
result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
|
||||
__func__, __LINE__, result);
|
||||
BUG_ON("check region type");
|
||||
goto clean_alloc;
|
||||
}
|
||||
|
||||
return (void*)virt_addr;
|
||||
|
||||
clean_alloc:
|
||||
free_pages(virt_addr, get_order(size));
|
||||
clean_none:
|
||||
dma_handle = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
|
||||
ps3_dma_unmap(dev->d_region, dma_handle, size);
|
||||
free_pages((unsigned long)vaddr, get_order(size));
|
||||
}
|
||||
|
||||
/* Creates TCEs for a user provided buffer. The user buffer must be
|
||||
* contiguous real kernel storage (not vmalloc). The address of the buffer
|
||||
* passed here is the kernel (virtual) address of the buffer. The buffer
|
||||
* need not be page aligned, the dma_addr_t returned will point to the same
|
||||
* byte within the page as vaddr.
|
||||
*/
|
||||
|
||||
static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
int result;
|
||||
unsigned long bus_addr;
|
||||
|
||||
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
|
||||
&bus_addr);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
|
||||
__func__, __LINE__, result);
|
||||
}
|
||||
|
||||
return bus_addr;
|
||||
}
|
||||
|
||||
static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
|
||||
size_t size, enum dma_data_direction direction)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
int result;
|
||||
|
||||
result = ps3_dma_unmap(dev->d_region, dma_addr, size);
|
||||
|
||||
if (result) {
|
||||
pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n",
|
||||
__func__, __LINE__, result);
|
||||
}
|
||||
}
|
||||
|
||||
static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
#if defined(CONFIG_PS3_DYNAMIC_DMA)
|
||||
BUG_ON("do");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
#if defined(CONFIG_PS3_DYNAMIC_DMA)
|
||||
BUG_ON("do");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ps3_dma_supported(struct device *_dev, u64 mask)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dma_mapping_ops ps3_dma_ops = {
|
||||
.alloc_coherent = ps3_alloc_coherent,
|
||||
.free_coherent = ps3_free_coherent,
|
||||
.map_single = ps3_map_single,
|
||||
.unmap_single = ps3_unmap_single,
|
||||
.map_sg = ps3_map_sg,
|
||||
.unmap_sg = ps3_unmap_sg,
|
||||
.dma_supported = ps3_dma_supported
|
||||
};
|
||||
|
||||
/**
|
||||
* ps3_system_bus_release_device - remove a device from the system bus
|
||||
*/
|
||||
|
||||
static void ps3_system_bus_release_device(struct device *_dev)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ps3_system_bus_device_register - add a device to the system bus
|
||||
*
|
||||
* ps3_system_bus_device_register() expects the dev object to be allocated
|
||||
* dynamically by the caller. The system bus takes ownership of the dev
|
||||
* object and frees the object in ps3_system_bus_release_device().
|
||||
*/
|
||||
|
||||
int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
|
||||
{
|
||||
int result;
|
||||
static unsigned int dev_count = 1;
|
||||
|
||||
dev->core.parent = NULL;
|
||||
dev->core.bus = &ps3_system_bus_type;
|
||||
dev->core.release = ps3_system_bus_release_device;
|
||||
|
||||
dev->core.archdata.of_node = NULL;
|
||||
dev->core.archdata.dma_ops = &ps3_dma_ops;
|
||||
dev->core.archdata.numa_node = 0;
|
||||
|
||||
snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x",
|
||||
dev_count++);
|
||||
|
||||
pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
|
||||
|
||||
result = device_register(&dev->core);
|
||||
return result;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ps3_system_bus_device_register);
|
||||
|
||||
int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv)
|
||||
{
|
||||
int result;
|
||||
|
||||
drv->core.bus = &ps3_system_bus_type;
|
||||
|
||||
result = driver_register(&drv->core);
|
||||
return result;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
|
||||
|
||||
void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
|
||||
{
|
||||
driver_unregister(&drv->core);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
|
||||
|
|
@ -1264,15 +1264,21 @@ __dasd_check_expire(struct dasd_device * device)
|
|||
if (list_empty(&device->ccw_queue))
|
||||
return;
|
||||
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
|
||||
if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
|
||||
if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
|
||||
if ((cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) &&
|
||||
(time_after_eq(jiffies, cqr->expires + cqr->starttime))) {
|
||||
if (device->discipline->term_IO(cqr) != 0) {
|
||||
/* Hmpf, try again in 5 sec */
|
||||
dasd_set_timer(device, 5*HZ);
|
||||
DEV_MESSAGE(KERN_ERR, device,
|
||||
"internal error - timeout (%is) expired "
|
||||
"for cqr %p, termination failed, "
|
||||
"retrying in 5s",
|
||||
(cqr->expires/HZ), cqr);
|
||||
} else {
|
||||
DEV_MESSAGE(KERN_ERR, device,
|
||||
"internal error - timeout (%is) expired "
|
||||
"for cqr %p (%i retries left)",
|
||||
(cqr->expires/HZ), cqr, cqr->retries);
|
||||
if (device->discipline->term_IO(cqr) != 0)
|
||||
/* Hmpf, try again in 1/10 sec */
|
||||
dasd_set_timer(device, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -684,21 +684,26 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
int ro_flag;
|
||||
int val;
|
||||
char *endp;
|
||||
|
||||
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
ro_flag = buf[0] == '1';
|
||||
|
||||
val = simple_strtoul(buf, &endp, 0);
|
||||
if (((endp + 1) < (buf + count)) || (val > 1))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
if (ro_flag)
|
||||
if (val)
|
||||
devmap->features |= DASD_FEATURE_READONLY;
|
||||
else
|
||||
devmap->features &= ~DASD_FEATURE_READONLY;
|
||||
if (devmap->device)
|
||||
devmap->device->features = devmap->features;
|
||||
if (devmap->device && devmap->device->gdp)
|
||||
set_disk_ro(devmap->device->gdp, ro_flag);
|
||||
set_disk_ro(devmap->device->gdp, val);
|
||||
spin_unlock(&dasd_devmap_lock);
|
||||
return count;
|
||||
}
|
||||
|
|
@ -729,17 +734,22 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
struct dasd_devmap *devmap;
|
||||
ssize_t rc;
|
||||
int use_diag;
|
||||
int val;
|
||||
char *endp;
|
||||
|
||||
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
use_diag = buf[0] == '1';
|
||||
|
||||
val = simple_strtoul(buf, &endp, 0);
|
||||
if (((endp + 1) < (buf + count)) || (val > 1))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
/* Changing diag discipline flag is only allowed in offline state. */
|
||||
rc = count;
|
||||
if (!devmap->device) {
|
||||
if (use_diag)
|
||||
if (val)
|
||||
devmap->features |= DASD_FEATURE_USEDIAG;
|
||||
else
|
||||
devmap->features &= ~DASD_FEATURE_USEDIAG;
|
||||
|
|
@ -854,14 +864,20 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
int rc;
|
||||
int val, rc;
|
||||
char *endp;
|
||||
|
||||
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
if (!devmap->device)
|
||||
return count;
|
||||
if (buf[0] == '1') {
|
||||
return -ENODEV;
|
||||
|
||||
val = simple_strtoul(buf, &endp, 0);
|
||||
if (((endp + 1) < (buf + count)) || (val > 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (val) {
|
||||
rc = dasd_eer_enable(devmap->device);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -299,14 +299,14 @@ raw3215_timeout(unsigned long __data)
|
|||
struct raw3215_info *raw = (struct raw3215_info *) __data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
if (raw->flags & RAW3215_TIMER_RUNS) {
|
||||
del_timer(&raw->timer);
|
||||
raw->flags &= ~RAW3215_TIMER_RUNS;
|
||||
raw3215_mk_write_req(raw);
|
||||
raw3215_start_io(raw);
|
||||
}
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -355,10 +355,10 @@ raw3215_tasklet(void *data)
|
|||
unsigned long flags;
|
||||
|
||||
raw = (struct raw3215_info *) data;
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_mk_write_req(raw);
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
/* Check for pending message from raw3215_irq */
|
||||
if (raw->message != NULL) {
|
||||
printk(raw->message, raw->msg_dstat, raw->msg_cstat);
|
||||
|
|
@ -512,9 +512,9 @@ raw3215_make_room(struct raw3215_info *raw, unsigned int length)
|
|||
if (RAW3215_BUFFER_SIZE - raw->count >= length)
|
||||
break;
|
||||
/* there might be another cpu waiting for the lock */
|
||||
spin_unlock(raw->lock);
|
||||
spin_unlock(get_ccwdev_lock(raw->cdev));
|
||||
udelay(100);
|
||||
spin_lock(raw->lock);
|
||||
spin_lock(get_ccwdev_lock(raw->cdev));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -528,7 +528,7 @@ raw3215_write(struct raw3215_info *raw, const char *str, unsigned int length)
|
|||
int c, count;
|
||||
|
||||
while (length > 0) {
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
count = (length > RAW3215_BUFFER_SIZE) ?
|
||||
RAW3215_BUFFER_SIZE : length;
|
||||
length -= count;
|
||||
|
|
@ -555,7 +555,7 @@ raw3215_write(struct raw3215_info *raw, const char *str, unsigned int length)
|
|||
/* start or queue request */
|
||||
raw3215_try_io(raw);
|
||||
}
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -568,7 +568,7 @@ raw3215_putchar(struct raw3215_info *raw, unsigned char ch)
|
|||
unsigned long flags;
|
||||
unsigned int length, i;
|
||||
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
if (ch == '\t') {
|
||||
length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE);
|
||||
raw->line_pos += length;
|
||||
|
|
@ -592,7 +592,7 @@ raw3215_putchar(struct raw3215_info *raw, unsigned char ch)
|
|||
/* start or queue request */
|
||||
raw3215_try_io(raw);
|
||||
}
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -604,13 +604,13 @@ raw3215_flush_buffer(struct raw3215_info *raw)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
if (raw->count > 0) {
|
||||
raw->flags |= RAW3215_FLUSHING;
|
||||
raw3215_try_io(raw);
|
||||
raw->flags &= ~RAW3215_FLUSHING;
|
||||
}
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -625,9 +625,9 @@ raw3215_startup(struct raw3215_info *raw)
|
|||
return 0;
|
||||
raw->line_pos = 0;
|
||||
raw->flags |= RAW3215_ACTIVE;
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -644,21 +644,21 @@ raw3215_shutdown(struct raw3215_info *raw)
|
|||
if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))
|
||||
return;
|
||||
/* Wait for outstanding requests, then free irq */
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
if ((raw->flags & RAW3215_WORKING) ||
|
||||
raw->queued_write != NULL ||
|
||||
raw->queued_read != NULL) {
|
||||
raw->flags |= RAW3215_CLOSING;
|
||||
add_wait_queue(&raw->empty_wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
schedule();
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
remove_wait_queue(&raw->empty_wait, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);
|
||||
}
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -686,7 +686,6 @@ raw3215_probe (struct ccw_device *cdev)
|
|||
}
|
||||
|
||||
raw->cdev = cdev;
|
||||
raw->lock = get_ccwdev_lock(cdev);
|
||||
raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
|
||||
memset(raw, 0, sizeof(struct raw3215_info));
|
||||
raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,
|
||||
|
|
@ -809,9 +808,9 @@ con3215_unblank(void)
|
|||
unsigned long flags;
|
||||
|
||||
raw = raw3215[0]; /* console 3215 is the first one */
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_make_room(raw, RAW3215_BUFFER_SIZE);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
static int __init
|
||||
|
|
@ -873,7 +872,6 @@ con3215_init(void)
|
|||
raw->buffer = (char *) alloc_bootmem_low(RAW3215_BUFFER_SIZE);
|
||||
raw->inbuf = (char *) alloc_bootmem_low(RAW3215_INBUF_SIZE);
|
||||
raw->cdev = cdev;
|
||||
raw->lock = get_ccwdev_lock(cdev);
|
||||
cdev->dev.driver_data = raw;
|
||||
cdev->handler = raw3215_irq;
|
||||
|
||||
|
|
@ -1066,10 +1064,10 @@ tty3215_unthrottle(struct tty_struct * tty)
|
|||
|
||||
raw = (struct raw3215_info *) tty->driver_data;
|
||||
if (raw->flags & RAW3215_THROTTLED) {
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw->flags &= ~RAW3215_THROTTLED;
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1096,10 +1094,10 @@ tty3215_start(struct tty_struct *tty)
|
|||
|
||||
raw = (struct raw3215_info *) tty->driver_data;
|
||||
if (raw->flags & RAW3215_STOPPED) {
|
||||
spin_lock_irqsave(raw->lock, flags);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw->flags &= ~RAW3215_STOPPED;
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(raw->lock, flags);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue