aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_hpt366.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-01-08 16:29:20 -0500
committerJeff Garzik <jgarzik@redhat.com>2009-01-08 16:29:20 -0500
commit6ecb6f25d3a52c0d032aa73bde1ff9bc454aa66c (patch)
tree3c4804660bbced95918b6d2e9dab06b3994846a9 /drivers/ata/pata_hpt366.c
parentb63d3953251f144b75993374d752e0d57034c8bb (diff)
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>
Diffstat (limited to 'drivers/ata/pata_hpt366.c')
-rw-r--r--drivers/ata/pata_hpt366.c109
1 files changed, 44 insertions, 65 deletions
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index e0c4f05d7d57..65c28e5a6cd7 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -30,7 +30,7 @@
30#define DRV_VERSION "0.6.2" 30#define DRV_VERSION "0.6.2"
31 31
32struct hpt_clock { 32struct hpt_clock {
33 u8 xfer_speed; 33 u8 xfer_mode;
34 u32 timing; 34 u32 timing;
35}; 35};
36 36
@@ -189,28 +189,6 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
189 return ata_bmdma_mode_filter(adev, mask); 189 return ata_bmdma_mode_filter(adev, mask);
190} 190}
191 191
192/**
193 * hpt36x_find_mode - reset the hpt36x bus
194 * @ap: ATA port
195 * @speed: transfer mode
196 *
197 * Return the 32bit register programming information for this channel
198 * that matches the speed provided.
199 */
200
201static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
202{
203 struct hpt_clock *clocks = ap->host->private_data;
204
205 while(clocks->xfer_speed) {
206 if (clocks->xfer_speed == speed)
207 return clocks->timing;
208 clocks++;
209 }
210 BUG();
211 return 0xffffffffU; /* silence compiler warning */
212}
213
214static int hpt36x_cable_detect(struct ata_port *ap) 192static int hpt36x_cable_detect(struct ata_port *ap)
215{ 193{
216 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 194 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -226,25 +204,16 @@ static int hpt36x_cable_detect(struct ata_port *ap)
226 return ATA_CBL_PATA80; 204 return ATA_CBL_PATA80;
227} 205}
228 206
229/** 207static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
230 * hpt366_set_piomode - PIO setup 208 u8 mode)
231 * @ap: ATA interface
232 * @adev: device on the interface
233 *
234 * Perform PIO mode setup.
235 */
236
237static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
238{ 209{
210 struct hpt_clock *clocks = ap->host->private_data;
239 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 211 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
240 u32 addr1, addr2; 212 u32 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
241 u32 reg; 213 u32 addr2 = 0x51 + 4 * ap->port_no;
242 u32 mode; 214 u32 mask, reg;
243 u8 fast; 215 u8 fast;
244 216
245 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
246 addr2 = 0x51 + 4 * ap->port_no;
247
248 /* Fast interrupt prediction disable, hold off interrupt disable */ 217 /* Fast interrupt prediction disable, hold off interrupt disable */
249 pci_read_config_byte(pdev, addr2, &fast); 218 pci_read_config_byte(pdev, addr2, &fast);
250 if (fast & 0x80) { 219 if (fast & 0x80) {
@@ -252,12 +221,43 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
252 pci_write_config_byte(pdev, addr2, fast); 221 pci_write_config_byte(pdev, addr2, fast);
253 } 222 }
254 223
224 /* determine timing mask and find matching clock entry */
225 if (mode < XFER_MW_DMA_0)
226 mask = 0xc1f8ffff;
227 else if (mode < XFER_UDMA_0)
228 mask = 0x303800ff;
229 else
230 mask = 0x30070000;
231
232 while (clocks->xfer_mode) {
233 if (clocks->xfer_mode == mode)
234 break;
235 clocks++;
236 }
237 if (!clocks->xfer_mode)
238 BUG();
239
240 /*
241 * Combine new mode bits with old config bits and disable
242 * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
243 * problems handling I/O errors later.
244 */
255 pci_read_config_dword(pdev, addr1, &reg); 245 pci_read_config_dword(pdev, addr1, &reg);
256 mode = hpt36x_find_mode(ap, adev->pio_mode); 246 reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
257 mode &= ~0x8000000; /* No FIFO in PIO */ 247 pci_write_config_dword(pdev, addr1, reg);
258 mode &= ~0x30070000; /* Leave config bits alone */ 248}
259 reg &= 0x30070000; /* Strip timing bits */ 249
260 pci_write_config_dword(pdev, addr1, reg | mode); 250/**
251 * hpt366_set_piomode - PIO setup
252 * @ap: ATA interface
253 * @adev: device on the interface
254 *
255 * Perform PIO mode setup.
256 */
257
258static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
259{
260 hpt366_set_mode(ap, adev, adev->pio_mode);
261} 261}
262 262
263/** 263/**
@@ -271,28 +271,7 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
271 271
272static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev) 272static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
273{ 273{
274 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 274 hpt366_set_mode(ap, adev, adev->dma_mode);
275 u32 addr1, addr2;
276 u32 reg;
277 u32 mode;
278 u8 fast;
279
280 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
281 addr2 = 0x51 + 4 * ap->port_no;
282
283 /* Fast interrupt prediction disable, hold off interrupt disable */
284 pci_read_config_byte(pdev, addr2, &fast);
285 if (fast & 0x80) {
286 fast &= ~0x80;
287 pci_write_config_byte(pdev, addr2, fast);
288 }
289
290 pci_read_config_dword(pdev, addr1, &reg);
291 mode = hpt36x_find_mode(ap, adev->dma_mode);
292 mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
293 mode &= ~0xC0000000; /* Leave config bits alone */
294 reg &= 0xC0000000; /* Strip timing bits */
295 pci_write_config_dword(pdev, addr1, reg | mode);
296} 275}
297 276
298static struct scsi_host_template hpt36x_sht = { 277static struct scsi_host_template hpt36x_sht = {