pata_hpt366: reimplement mode programming
Reimplement mode programming logic of pata_hpt366 such that it's identical to that of IDE hpt366 driver. The differences were... * pata_hpt366 used 0xCFFF8FFFF to mask pio modes and 0x3FFFFFFF dma modes. IDE hpt366 uses 0xC1F8FFFF for PIO, 0x303800FF for MWDMA and 0x30070000 for UDMA. * pata_hpt366 doesn't set 0x08000000 for PIO unless it's already set and always turns it on for MWDMA/UDMA. IDE hpt366 doesn't bother with the bit. It always uses what was there. * IDE hpt366 always clears 0xC0000000. pata_hpt366 doesn't. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								b63d395325
							
						
					
				
			
			
				commit
				
					
						6ecb6f25d3
					
				
			
		
					 1 changed files with 46 additions and 67 deletions
				
			
		| 
						 | 
					@ -30,7 +30,7 @@
 | 
				
			||||||
#define DRV_VERSION	"0.6.2"
 | 
					#define DRV_VERSION	"0.6.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct hpt_clock {
 | 
					struct hpt_clock {
 | 
				
			||||||
	u8	xfer_speed;
 | 
						u8	xfer_mode;
 | 
				
			||||||
	u32	timing;
 | 
						u32	timing;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -189,28 +189,6 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
 | 
				
			||||||
	return ata_bmdma_mode_filter(adev, mask);
 | 
						return ata_bmdma_mode_filter(adev, mask);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *	hpt36x_find_mode	-	reset the hpt36x bus
 | 
					 | 
				
			||||||
 *	@ap: ATA port
 | 
					 | 
				
			||||||
 *	@speed: transfer mode
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *	Return the 32bit register programming information for this channel
 | 
					 | 
				
			||||||
 *	that matches the speed provided.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct hpt_clock *clocks = ap->host->private_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while(clocks->xfer_speed) {
 | 
					 | 
				
			||||||
		if (clocks->xfer_speed == speed)
 | 
					 | 
				
			||||||
			return clocks->timing;
 | 
					 | 
				
			||||||
		clocks++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	BUG();
 | 
					 | 
				
			||||||
	return 0xffffffffU;	/* silence compiler warning */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int hpt36x_cable_detect(struct ata_port *ap)
 | 
					static int hpt36x_cable_detect(struct ata_port *ap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 | 
						struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 | 
				
			||||||
| 
						 | 
					@ -226,6 +204,49 @@ static int hpt36x_cable_detect(struct ata_port *ap)
 | 
				
			||||||
	return ATA_CBL_PATA80;
 | 
						return ATA_CBL_PATA80;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
 | 
				
			||||||
 | 
								    u8 mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hpt_clock *clocks = ap->host->private_data;
 | 
				
			||||||
 | 
						struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 | 
				
			||||||
 | 
						u32 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
 | 
				
			||||||
 | 
						u32 addr2 = 0x51 + 4 * ap->port_no;
 | 
				
			||||||
 | 
						u32 mask, reg;
 | 
				
			||||||
 | 
						u8 fast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fast interrupt prediction disable, hold off interrupt disable */
 | 
				
			||||||
 | 
						pci_read_config_byte(pdev, addr2, &fast);
 | 
				
			||||||
 | 
						if (fast & 0x80) {
 | 
				
			||||||
 | 
							fast &= ~0x80;
 | 
				
			||||||
 | 
							pci_write_config_byte(pdev, addr2, fast);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* determine timing mask and find matching clock entry */
 | 
				
			||||||
 | 
						if (mode < XFER_MW_DMA_0)
 | 
				
			||||||
 | 
							mask = 0xc1f8ffff;
 | 
				
			||||||
 | 
						else if (mode < XFER_UDMA_0)
 | 
				
			||||||
 | 
							mask = 0x303800ff;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							mask = 0x30070000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (clocks->xfer_mode) {
 | 
				
			||||||
 | 
							if (clocks->xfer_mode == mode)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							clocks++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!clocks->xfer_mode)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Combine new mode bits with old config bits and disable
 | 
				
			||||||
 | 
						 * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
 | 
				
			||||||
 | 
						 * problems handling I/O errors later.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						pci_read_config_dword(pdev, addr1, ®);
 | 
				
			||||||
 | 
						reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
 | 
				
			||||||
 | 
						pci_write_config_dword(pdev, addr1, reg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	hpt366_set_piomode		-	PIO setup
 | 
					 *	hpt366_set_piomode		-	PIO setup
 | 
				
			||||||
 *	@ap: ATA interface
 | 
					 *	@ap: ATA interface
 | 
				
			||||||
| 
						 | 
					@ -236,28 +257,7 @@ static int hpt36x_cable_detect(struct ata_port *ap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
					static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 | 
						hpt366_set_mode(ap, adev, adev->pio_mode);
 | 
				
			||||||
	u32 addr1, addr2;
 | 
					 | 
				
			||||||
	u32 reg;
 | 
					 | 
				
			||||||
	u32 mode;
 | 
					 | 
				
			||||||
	u8 fast;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
 | 
					 | 
				
			||||||
	addr2 = 0x51 + 4 * ap->port_no;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Fast interrupt prediction disable, hold off interrupt disable */
 | 
					 | 
				
			||||||
	pci_read_config_byte(pdev, addr2, &fast);
 | 
					 | 
				
			||||||
	if (fast & 0x80) {
 | 
					 | 
				
			||||||
		fast &= ~0x80;
 | 
					 | 
				
			||||||
		pci_write_config_byte(pdev, addr2, fast);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_read_config_dword(pdev, addr1, ®);
 | 
					 | 
				
			||||||
	mode = hpt36x_find_mode(ap, adev->pio_mode);
 | 
					 | 
				
			||||||
	mode &= ~0x8000000;	/* No FIFO in PIO */
 | 
					 | 
				
			||||||
	mode &= ~0x30070000;	/* Leave config bits alone */
 | 
					 | 
				
			||||||
	reg &= 0x30070000;	/* Strip timing bits */
 | 
					 | 
				
			||||||
	pci_write_config_dword(pdev, addr1, reg | mode);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -271,28 +271,7 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 | 
					static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 | 
						hpt366_set_mode(ap, adev, adev->dma_mode);
 | 
				
			||||||
	u32 addr1, addr2;
 | 
					 | 
				
			||||||
	u32 reg;
 | 
					 | 
				
			||||||
	u32 mode;
 | 
					 | 
				
			||||||
	u8 fast;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
 | 
					 | 
				
			||||||
	addr2 = 0x51 + 4 * ap->port_no;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Fast interrupt prediction disable, hold off interrupt disable */
 | 
					 | 
				
			||||||
	pci_read_config_byte(pdev, addr2, &fast);
 | 
					 | 
				
			||||||
	if (fast & 0x80) {
 | 
					 | 
				
			||||||
		fast &= ~0x80;
 | 
					 | 
				
			||||||
		pci_write_config_byte(pdev, addr2, fast);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_read_config_dword(pdev, addr1, ®);
 | 
					 | 
				
			||||||
	mode = hpt36x_find_mode(ap, adev->dma_mode);
 | 
					 | 
				
			||||||
	mode |= 0x8000000;	/* FIFO in MWDMA or UDMA */
 | 
					 | 
				
			||||||
	mode &= ~0xC0000000;	/* Leave config bits alone */
 | 
					 | 
				
			||||||
	reg &= 0xC0000000;	/* Strip timing bits */
 | 
					 | 
				
			||||||
	pci_write_config_dword(pdev, addr1, reg | mode);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct scsi_host_template hpt36x_sht = {
 | 
					static struct scsi_host_template hpt36x_sht = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue