@ -24,7 +24,7 @@
# include <linux/libata.h>
# define DRV_NAME "pata_amd"
# define DRV_VERSION "0.3.1 1"
# define DRV_VERSION "0.4. 1"
/**
* 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 ) ;
}
/**
* 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 const u32 bitmask [ 2 ] = { 0x03 , 0x0C } ;
@ -157,6 +164,40 @@ static int amd_cable_detect(struct ata_port *ap)
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
* @ 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 )
{
amd_fifo_setup ( ap ) ;
timing_setup ( ap , adev , 0x40 , adev - > pio_mode , 1 ) ;
}
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 ) ;
}
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 ) ;
}
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 ) ;
}
@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = {
. 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 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 )
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,
* cache BIOS programmed UDMA mode .
*/
@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
return rc ;
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 | |
pdev - > device = = PCI_DEVICE_ID_AMD_COBRA_7401 )
ata_pci_bmdma_clear_simplex ( pdev ) ;
}
ata_host_resume ( host ) ;
return 0 ;
}