aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_hpt3x2n.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/pata_hpt3x2n.c')
-rw-r--r--drivers/ata/pata_hpt3x2n.c69
1 files changed, 31 insertions, 38 deletions
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 269b5dbe51bb..b131c8f824d7 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -25,7 +25,7 @@
25#include <linux/libata.h> 25#include <linux/libata.h>
26 26
27#define DRV_NAME "pata_hpt3x2n" 27#define DRV_NAME "pata_hpt3x2n"
28#define DRV_VERSION "0.3.9" 28#define DRV_VERSION "0.3.10"
29 29
30enum { 30enum {
31 HPT_PCI_FAST = (1 << 31), 31 HPT_PCI_FAST = (1 << 31),
@@ -161,20 +161,12 @@ static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
161 return ata_sff_prereset(link, deadline); 161 return ata_sff_prereset(link, deadline);
162} 162}
163 163
164/** 164static void hpt3x2n_set_mode(struct ata_port *ap, struct ata_device *adev,
165 * hpt3x2n_set_piomode - PIO setup 165 u8 mode)
166 * @ap: ATA interface
167 * @adev: device on the interface
168 *
169 * Perform PIO mode setup.
170 */
171
172static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
173{ 166{
174 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 167 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
175 u32 addr1, addr2; 168 u32 addr1, addr2;
176 u32 reg; 169 u32 reg, timing, mask;
177 u32 mode;
178 u8 fast; 170 u8 fast;
179 171
180 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 172 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -185,11 +177,32 @@ static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
185 fast &= ~0x07; 177 fast &= ~0x07;
186 pci_write_config_byte(pdev, addr2, fast); 178 pci_write_config_byte(pdev, addr2, fast);
187 179
180 /* Determine timing mask and find matching mode entry */
181 if (mode < XFER_MW_DMA_0)
182 mask = 0xcfc3ffff;
183 else if (mode < XFER_UDMA_0)
184 mask = 0x31c001ff;
185 else
186 mask = 0x303c0000;
187
188 timing = hpt3x2n_find_mode(ap, mode);
189
188 pci_read_config_dword(pdev, addr1, &reg); 190 pci_read_config_dword(pdev, addr1, &reg);
189 mode = hpt3x2n_find_mode(ap, adev->pio_mode); 191 reg = (reg & ~mask) | (timing & mask);
190 mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ 192 pci_write_config_dword(pdev, addr1, reg);
191 reg &= ~0xCFC3FFFF; /* Strip timing bits */ 193}
192 pci_write_config_dword(pdev, addr1, reg | mode); 194
195/**
196 * hpt3x2n_set_piomode - PIO setup
197 * @ap: ATA interface
198 * @adev: device on the interface
199 *
200 * Perform PIO mode setup.
201 */
202
203static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
204{
205 hpt3x2n_set_mode(ap, adev, adev->pio_mode);
193} 206}
194 207
195/** 208/**
@@ -197,32 +210,12 @@ static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
197 * @ap: ATA interface 210 * @ap: ATA interface
198 * @adev: Device being configured 211 * @adev: Device being configured
199 * 212 *
200 * Set up the channel for MWDMA or UDMA modes. Much the same as with 213 * Set up the channel for MWDMA or UDMA modes.
201 * PIO, load the mode number and then set MWDMA or UDMA flag.
202 */ 214 */
203 215
204static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev) 216static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
205{ 217{
206 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 218 hpt3x2n_set_mode(ap, adev, adev->dma_mode);
207 u32 addr1, addr2;
208 u32 reg, mode, mask;
209 u8 fast;
210
211 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
212 addr2 = 0x51 + 4 * ap->port_no;
213
214 /* Fast interrupt prediction disable, hold off interrupt disable */
215 pci_read_config_byte(pdev, addr2, &fast);
216 fast &= ~0x07;
217 pci_write_config_byte(pdev, addr2, fast);
218
219 mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
220
221 pci_read_config_dword(pdev, addr1, &reg);
222 mode = hpt3x2n_find_mode(ap, adev->dma_mode);
223 mode &= mask;
224 reg &= ~mask;
225 pci_write_config_dword(pdev, addr1, reg | mode);
226} 219}
227 220
228/** 221/**