aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_sis.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2009-12-07 11:41:25 -0500
committerJeff Garzik <jgarzik@redhat.com>2009-12-07 11:41:25 -0500
commit1b52f2a41c41052d2a7c78af0bd9b8b11d70f49a (patch)
treef71bd703c40d3b5dec2e9db074e2ea43c0d8f4a5 /drivers/ata/pata_sis.c
parentd0634c4aea0b80447cbdc4c0db285004b860c455 (diff)
Revert "pata_sis: Implement MWDMA for the UDMA 133 capable chips"
This reverts commit f20941f334d8fdb6b598658979709b4e94cd034b. Sergei Shtylyov notes "You call min() on uncomparables [in mwdma_clip_to_pio()], i.e. mwdma_to_pio[] contains XFER_PIO_* and adev->pio_mode - XFER_PIO_0 yields you a mode number. Thus the second argument will always "win" as a minimal one" Bartlomiej Zolnierkiewicz adds "There are more issues with the patch related to mwdma_clip_to_pio(). The function can return values between 0 and 4 which obviously won't work well for the new code below for values >2 (i.e. resulting in out-of-bounds array access for the common-case of dev->pio_mode == XFER_PIO_4)." Bartlomiej Zolnierkiewicz also notes the patch is incomplete, failing to update MWDMA mode masks. Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_sis.c')
-rw-r--r--drivers/ata/pata_sis.c91
1 files changed, 22 insertions, 69 deletions
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 8af0dc88fd98..5c30d56dec84 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -252,25 +252,24 @@ static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
252} 252}
253 253
254/** 254/**
255 * sis_133_do_piomode - Initialize host controller PATA PIO/DMA timings 255 * sis_133_set_piomode - Initialize host controller PATA PIO timings
256 * @ap: Port whose timings we are configuring 256 * @ap: Port whose timings we are configuring
257 * @adev: Device we are configuring for. 257 * @adev: Device we are configuring for.
258 * 258 *
259 * Set PIO mode for device, in host controller PCI config space. This 259 * Set PIO mode for device, in host controller PCI config space. This
260 * function handles PIO set up for the later ATA133 devices. The same 260 * function handles PIO set up for the later ATA133 devices.
261 * timings are used for MWDMA.
262 * 261 *
263 * LOCKING: 262 * LOCKING:
264 * None (inherited from caller). 263 * None (inherited from caller).
265 */ 264 */
266 265
267static void sis_133_do_piomode(struct ata_port *ap, struct ata_device *adev, 266static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
268 int speed)
269{ 267{
270 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 268 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
271 int port = 0x40; 269 int port = 0x40;
272 u32 t1; 270 u32 t1;
273 u32 reg54; 271 u32 reg54;
272 int speed = adev->pio_mode - XFER_PIO_0;
274 273
275 const u32 timing133[] = { 274 const u32 timing133[] = {
276 0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */ 275 0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */
@@ -306,42 +305,6 @@ static void sis_133_do_piomode(struct ata_port *ap, struct ata_device *adev,
306} 305}
307 306
308/** 307/**
309 * sis_133_set_piomode - Initialize host controller PATA PIO timings
310 * @ap: Port whose timings we are configuring
311 * @adev: Device we are configuring for.
312 *
313 * Set PIO mode for device, in host controller PCI config space. This
314 * function handles PIO set up for the later ATA133 devices.
315 *
316 * LOCKING:
317 * None (inherited from caller).
318 */
319
320static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
321{
322
323 sis_133_do_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
324}
325
326/**
327 * mwdma_clip_to_pio - clip MWDMA mode
328 * @adev: device
329 *
330 * As the SiS shared MWDMA and PIO timings we must program the equivalent
331 * PIO timing for the MWDMA mode but we must not program one higher than
332 * the permitted PIO timing of the device.
333 */
334
335static int mwdma_clip_to_pio(struct ata_device *adev)
336{
337 const int mwdma_to_pio[3] = {
338 XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
339 };
340 return min(mwdma_to_pio[adev->dma_mode - XFER_MW_DMA_0],
341 adev->pio_mode - XFER_PIO_0);
342}
343
344/**
345 * sis_old_set_dmamode - Initialize host controller PATA DMA timings 308 * sis_old_set_dmamode - Initialize host controller PATA DMA timings
346 * @ap: Port whose timings we are configuring 309 * @ap: Port whose timings we are configuring
347 * @adev: Device to program 310 * @adev: Device to program
@@ -369,7 +332,6 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
369 if (adev->dma_mode < XFER_UDMA_0) { 332 if (adev->dma_mode < XFER_UDMA_0) {
370 /* bits 3-0 hold recovery timing bits 8-10 active timing and 333 /* bits 3-0 hold recovery timing bits 8-10 active timing and
371 the higher bits are dependant on the device */ 334 the higher bits are dependant on the device */
372 speed = mwdma_clip_to_pio(adev);
373 timing &= ~0x870F; 335 timing &= ~0x870F;
374 timing |= mwdma_bits[speed]; 336 timing |= mwdma_bits[speed];
375 } else { 337 } else {
@@ -410,7 +372,6 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
410 if (adev->dma_mode < XFER_UDMA_0) { 372 if (adev->dma_mode < XFER_UDMA_0) {
411 /* bits 3-0 hold recovery timing bits 8-10 active timing and 373 /* bits 3-0 hold recovery timing bits 8-10 active timing and
412 the higher bits are dependant on the device, bit 15 udma */ 374 the higher bits are dependant on the device, bit 15 udma */
413 speed = mwdma_clip_to_pio(adev);
414 timing &= ~0x870F; 375 timing &= ~0x870F;
415 timing |= mwdma_bits[speed]; 376 timing |= mwdma_bits[speed];
416 } else { 377 } else {
@@ -428,7 +389,7 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
428 * @adev: Device to program 389 * @adev: Device to program
429 * 390 *
430 * Set UDMA/MWDMA mode for device, in host controller PCI config space. 391 * Set UDMA/MWDMA mode for device, in host controller PCI config space.
431 * Handles later UDMA100 devices. 392 * Handles UDMA66 and early UDMA100 devices.
432 * 393 *
433 * LOCKING: 394 * LOCKING:
434 * None (inherited from caller). 395 * None (inherited from caller).
@@ -439,25 +400,21 @@ static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
439 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 400 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
440 int speed = adev->dma_mode - XFER_MW_DMA_0; 401 int speed = adev->dma_mode - XFER_MW_DMA_0;
441 int drive_pci = sis_old_port_base(adev); 402 int drive_pci = sis_old_port_base(adev);
442 u16 timing; 403 u8 timing;
443 404
444 const u16 udma_bits[] = { 405 const u8 udma_bits[] = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
445 0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100};
446 const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };
447 406
448 pci_read_config_word(pdev, drive_pci, &timing); 407 pci_read_config_byte(pdev, drive_pci + 1, &timing);
449 408
450 if (adev->dma_mode < XFER_UDMA_0) { 409 if (adev->dma_mode < XFER_UDMA_0) {
451 speed = mwdma_clip_to_pio(adev); 410 /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
452 timing &= ~0x80FF;
453 timing |= mwdma_bits[speed];
454 } else { 411 } else {
455 /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */ 412 /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
456 speed = adev->dma_mode - XFER_UDMA_0; 413 speed = adev->dma_mode - XFER_UDMA_0;
457 timing &= ~0x8F00; 414 timing &= ~0x8F;
458 timing |= udma_bits[speed]; 415 timing |= udma_bits[speed];
459 } 416 }
460 pci_write_config_word(pdev, drive_pci, timing); 417 pci_write_config_byte(pdev, drive_pci + 1, timing);
461} 418}
462 419
463/** 420/**
@@ -477,26 +434,21 @@ static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *a
477 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 434 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
478 int speed = adev->dma_mode - XFER_MW_DMA_0; 435 int speed = adev->dma_mode - XFER_MW_DMA_0;
479 int drive_pci = sis_old_port_base(adev); 436 int drive_pci = sis_old_port_base(adev);
480 u16 timing; 437 u8 timing;
481 /* Bits 15-12 are timing */ 438 /* Low 4 bits are timing */
482 static const u16 udma_bits[] = { 439 static const u8 udma_bits[] = { 0x8F, 0x8A, 0x87, 0x85, 0x83, 0x82, 0x81};
483 0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100
484 };
485 static const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };
486 440
487 pci_read_config_word(pdev, drive_pci, &timing); 441 pci_read_config_byte(pdev, drive_pci + 1, &timing);
488 442
489 if (adev->dma_mode < XFER_UDMA_0) { 443 if (adev->dma_mode < XFER_UDMA_0) {
490 speed = mwdma_clip_to_pio(adev); 444 /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
491 timing &= ~0x80FF;
492 timing = mwdma_bits[speed];
493 } else { 445 } else {
494 /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */ 446 /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
495 speed = adev->dma_mode - XFER_UDMA_0; 447 speed = adev->dma_mode - XFER_UDMA_0;
496 timing &= ~0x8F00; 448 timing &= ~0x8F;
497 timing |= udma_bits[speed]; 449 timing |= udma_bits[speed];
498 } 450 }
499 pci_write_config_word(pdev, drive_pci, timing); 451 pci_write_config_byte(pdev, drive_pci + 1, timing);
500} 452}
501 453
502/** 454/**
@@ -527,12 +479,13 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
527 if (reg54 & 0x40000000) 479 if (reg54 & 0x40000000)
528 port = 0x70; 480 port = 0x70;
529 port += (8 * ap->port_no) + (4 * adev->devno); 481 port += (8 * ap->port_no) + (4 * adev->devno);
482
530 pci_read_config_dword(pdev, port, &t1); 483 pci_read_config_dword(pdev, port, &t1);
531 484
532 if (adev->dma_mode < XFER_UDMA_0) { 485 if (adev->dma_mode < XFER_UDMA_0) {
533 speed = mwdma_clip_to_pio(adev); 486 t1 &= ~0x00000004;
534 sis_133_do_piomode(ap, adev, speed); 487 /* FIXME: need data sheet to add MWDMA here. Also lacking on
535 t1 &= ~4; /* UDMA off */ 488 ide/pci driver */
536 } else { 489 } else {
537 speed = adev->dma_mode - XFER_UDMA_0; 490 speed = adev->dma_mode - XFER_UDMA_0;
538 /* if & 8 no UDMA133 - need info for ... */ 491 /* if & 8 no UDMA133 - need info for ... */