|
@@ -24,7 +24,7 @@
|
|
#include <linux/libata.h>
|
|
#include <linux/libata.h>
|
|
|
|
|
|
#define DRV_NAME "pata_amd"
|
|
#define DRV_NAME "pata_amd"
|
|
-#define DRV_VERSION "0.3.11"
|
|
|
|
|
|
+#define DRV_VERSION "0.4.1"
|
|
|
|
|
|
/**
|
|
/**
|
|
* timing_setup - shared timing computation and load
|
|
* timing_setup - shared timing computation and load
|
|
@@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
|
|
return ata_sff_prereset(link, deadline);
|
|
return ata_sff_prereset(link, deadline);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * amd_cable_detect - report cable type
|
|
|
|
+ * @ap: port
|
|
|
|
+ *
|
|
|
|
+ * AMD controller/BIOS setups record the cable type in word 0x42
|
|
|
|
+ */
|
|
|
|
+
|
|
static int amd_cable_detect(struct ata_port *ap)
|
|
static int amd_cable_detect(struct ata_port *ap)
|
|
{
|
|
{
|
|
static const u32 bitmask[2] = {0x03, 0x0C};
|
|
static const u32 bitmask[2] = {0x03, 0x0C};
|
|
@@ -157,6 +164,40 @@ static int amd_cable_detect(struct ata_port *ap)
|
|
return ATA_CBL_PATA40;
|
|
return ATA_CBL_PATA40;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * amd_fifo_setup - set the PIO FIFO for ATA/ATAPI
|
|
|
|
+ * @ap: ATA interface
|
|
|
|
+ * @adev: ATA device
|
|
|
|
+ *
|
|
|
|
+ * Set the PCI fifo for this device according to the devices present
|
|
|
|
+ * on the bus at this point in time. We need to turn the post write buffer
|
|
|
|
+ * off for ATAPI devices as we may need to issue a word sized write to the
|
|
|
|
+ * device as the final I/O
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static void amd_fifo_setup(struct ata_port *ap)
|
|
|
|
+{
|
|
|
|
+ struct ata_device *adev;
|
|
|
|
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
|
|
|
+ static const u8 fifobit[2] = { 0xC0, 0x30};
|
|
|
|
+ u8 fifo = fifobit[ap->port_no];
|
|
|
|
+ u8 r;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ata_for_each_dev(adev, &ap->link, ENABLED) {
|
|
|
|
+ if (adev->class == ATA_DEV_ATAPI)
|
|
|
|
+ fifo = 0;
|
|
|
|
+ }
|
|
|
|
+ if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */
|
|
|
|
+ fifo = 0;
|
|
|
|
+
|
|
|
|
+ /* On the later chips the read prefetch bits become no-op bits */
|
|
|
|
+ pci_read_config_byte(pdev, 0x41, &r);
|
|
|
|
+ r &= ~fifobit[ap->port_no];
|
|
|
|
+ r |= fifo;
|
|
|
|
+ pci_write_config_byte(pdev, 0x41, r);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* amd33_set_piomode - set initial PIO mode data
|
|
* amd33_set_piomode - set initial PIO mode data
|
|
* @ap: ATA interface
|
|
* @ap: ATA interface
|
|
@@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap)
|
|
|
|
|
|
static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
{
|
|
{
|
|
|
|
+ amd_fifo_setup(ap);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
|
|
}
|
|
}
|
|
|
|
|
|
static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
{
|
|
{
|
|
|
|
+ amd_fifo_setup(ap);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
|
|
}
|
|
}
|
|
|
|
|
|
static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
{
|
|
{
|
|
|
|
+ amd_fifo_setup(ap);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
|
|
}
|
|
}
|
|
|
|
|
|
static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|
{
|
|
{
|
|
|
|
+ amd_fifo_setup(ap);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
|
|
timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = {
|
|
.set_dmamode = nv133_set_dmamode,
|
|
.set_dmamode = nv133_set_dmamode,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static void amd_clear_fifo(struct pci_dev *pdev)
|
|
|
|
+{
|
|
|
|
+ u8 fifo;
|
|
|
|
+ /* Disable the FIFO, the FIFO logic will re-enable it as
|
|
|
|
+ appropriate */
|
|
|
|
+ pci_read_config_byte(pdev, 0x41, &fifo);
|
|
|
|
+ fifo &= 0x0F;
|
|
|
|
+ pci_write_config_byte(pdev, 0x41, fifo);
|
|
|
|
+}
|
|
|
|
+
|
|
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
{
|
|
static const struct ata_port_info info[10] = {
|
|
static const struct ata_port_info info[10] = {
|
|
@@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
|
|
|
if (type < 3)
|
|
if (type < 3)
|
|
ata_pci_bmdma_clear_simplex(pdev);
|
|
ata_pci_bmdma_clear_simplex(pdev);
|
|
-
|
|
|
|
- /* Check for AMD7411 */
|
|
|
|
- if (type == 3)
|
|
|
|
- /* FIFO is broken */
|
|
|
|
- pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
|
|
|
|
- else
|
|
|
|
- pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
|
|
|
|
-
|
|
|
|
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_AMD)
|
|
|
|
+ amd_clear_fifo(pdev);
|
|
/* Cable detection on Nvidia chips doesn't work too well,
|
|
/* Cable detection on Nvidia chips doesn't work too well,
|
|
* cache BIOS programmed UDMA mode.
|
|
* cache BIOS programmed UDMA mode.
|
|
*/
|
|
*/
|
|
@@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_AMD) {
|
|
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);
|
|
|
|
|
|
+ amd_clear_fifo(pdev);
|
|
if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
|
|
if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
|
|
pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
|
|
pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
|
|
ata_pci_bmdma_clear_simplex(pdev);
|
|
ata_pci_bmdma_clear_simplex(pdev);
|
|
}
|
|
}
|
|
-
|
|
|
|
ata_host_resume(host);
|
|
ata_host_resume(host);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|