Commit 88da4c77 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.8-pre2 IDE 29b

- Eliminate the mate member of the ata_channel structure. The information
   provided by it is already present. This patch may have undesirable
   effects on the ns87415.c and trm290.c host chip drivers, but it's worth
   for structural reasons to have it.

- Kill unused code, which was "fixing" interrupt routing from ide-pci.c Don't
   pass any "mate" between the functions there.

- Don't define SUPPORT_VLB_SYNC unconditionally in ide-taskfile.c

- Apply Vojtech Pavliks fix for piix host-chip driver crashes.

- Add linux/types.h to ide-pnp.c.

- Apply latest sis5513 host chip driver patch from by Lionel Bouton by hand.

- Apply patch by Paul Macerras for power-mac.

- Try to make the ns87415 driver a bit more reentrant.
parent 6e16d892
...@@ -1386,6 +1386,13 @@ P: Ingo Molnar ...@@ -1386,6 +1386,13 @@ P: Ingo Molnar
M: mingo@redhat.com M: mingo@redhat.com
S: Maintained S: Maintained
SIS 5513 IDE CONTROLLER DRIVER
P: Lionel Bouton
M: Lionel.Bouton@inet6.fr
W: http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html
W: http://gyver.homeip.net/sis5513/index.html
S: Maintained
SIS 900/7016 FAST ETHERNET DRIVER SIS 900/7016 FAST ETHERNET DRIVER
P: Ollie Lho P: Ollie Lho
M: ollie@sis.com.tw M: ollie@sis.com.tw
......
...@@ -212,9 +212,8 @@ void __init init_ali14xx (void) ...@@ -212,9 +212,8 @@ void __init init_ali14xx (void)
ide_hwifs[1].chipset = ide_ali14xx; ide_hwifs[1].chipset = ide_ali14xx;
ide_hwifs[0].tuneproc = &ali14xx_tune_drive; ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
ide_hwifs[1].tuneproc = &ali14xx_tune_drive; ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
ide_hwifs[0].mate = &ide_hwifs[1]; ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].unit = ATA_SECONDARY;
ide_hwifs[1].unit = 1;
/* initialize controller registers */ /* initialize controller registers */
if (!initRegisters()) { if (!initRegisters()) {
......
...@@ -689,7 +689,7 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) ...@@ -689,7 +689,7 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted)
/* /*
* Probe for a cmd640 chipset, and initialize it if found. Called from ide.c * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c
*/ */
int __init ide_probe_for_cmd640x (void) int __init ide_probe_for_cmd640x(void)
{ {
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
int second_port_toggled = 0; int second_port_toggled = 0;
...@@ -793,9 +793,7 @@ int __init ide_probe_for_cmd640x (void) ...@@ -793,9 +793,7 @@ int __init ide_probe_for_cmd640x (void)
cmd_hwif0->serialized = 1; cmd_hwif0->serialized = 1;
cmd_hwif1->serialized = 1; cmd_hwif1->serialized = 1;
cmd_hwif1->chipset = ide_cmd640; cmd_hwif1->chipset = ide_cmd640;
cmd_hwif0->mate = cmd_hwif1; cmd_hwif1->unit = ATA_SECONDARY;
cmd_hwif1->mate = cmd_hwif0;
cmd_hwif1->unit = 1;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
cmd_hwif1->tuneproc = &cmd640_tune_drive; cmd_hwif1->tuneproc = &cmd640_tune_drive;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
......
...@@ -346,8 +346,7 @@ unsigned int __init pci_init_cs5530(struct pci_dev *dev) ...@@ -346,8 +346,7 @@ unsigned int __init pci_init_cs5530(struct pci_dev *dev)
*/ */
void __init ide_init_cs5530(struct ata_channel *hwif) void __init ide_init_cs5530(struct ata_channel *hwif)
{ {
if (hwif->mate) hwif->serialized = 1;
hwif->serialized = hwif->mate->serialized = 1;
if (!hwif->dma_base) { if (!hwif->dma_base) {
hwif->autodma = 0; hwif->autodma = 0;
} else { } else {
......
...@@ -124,7 +124,6 @@ void __init init_dtc2278 (void) ...@@ -124,7 +124,6 @@ void __init init_dtc2278 (void)
ide_hwifs[0].drives[1].no_unmask = 1; ide_hwifs[0].drives[1].no_unmask = 1;
ide_hwifs[1].drives[0].no_unmask = 1; ide_hwifs[1].drives[0].no_unmask = 1;
ide_hwifs[1].drives[1].no_unmask = 1; ide_hwifs[1].drives[1].no_unmask = 1;
ide_hwifs[0].mate = &ide_hwifs[1]; ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].unit = ATA_SECONDARY;
ide_hwifs[1].unit = 1;
} }
...@@ -1131,7 +1131,7 @@ unsigned int __init pci_init_hpt366(struct pci_dev *dev) ...@@ -1131,7 +1131,7 @@ unsigned int __init pci_init_hpt366(struct pci_dev *dev)
hpt366_proc = 1; hpt366_proc = 1;
hpt366_display_info = &hpt366_get_info; hpt366_display_info = &hpt366_get_info;
} }
#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ #endif
return dev->irq; return dev->irq;
} }
...@@ -1146,7 +1146,7 @@ unsigned int __init ata66_hpt366(struct ata_channel *hwif) ...@@ -1146,7 +1146,7 @@ unsigned int __init ata66_hpt366(struct ata_channel *hwif)
printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
ata66, (ata66 & regmask) ? "33" : "66", ata66, (ata66 & regmask) ? "33" : "66",
PCI_FUNC(hwif->pci_dev->devfn)); PCI_FUNC(hwif->pci_dev->devfn));
#endif /* DEBUG */ #endif
return ((ata66 & regmask) ? 0 : 1); return ((ata66 & regmask) ? 0 : 1);
} }
......
...@@ -319,9 +319,8 @@ void __init init_ht6560b (void) ...@@ -319,9 +319,8 @@ void __init init_ht6560b (void)
ide_hwifs[1].tuneproc = &tune_ht6560b; ide_hwifs[1].tuneproc = &tune_ht6560b;
ide_hwifs[0].serialized = 1; /* is this needed? */ ide_hwifs[0].serialized = 1; /* is this needed? */
ide_hwifs[1].serialized = 1; /* is this needed? */ ide_hwifs[1].serialized = 1; /* is this needed? */
ide_hwifs[0].mate = &ide_hwifs[1]; ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].unit = ATA_SECONDARY;
ide_hwifs[1].unit = 1;
/* /*
* Setting default configurations for drives * Setting default configurations for drives
......
...@@ -421,7 +421,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad) ...@@ -421,7 +421,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad)
return 0; return 0;
} }
static int report_drive_dmaing (ide_drive_t *drive) int report_drive_dmaing (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
......
...@@ -182,7 +182,7 @@ typedef struct ide_pci_device_s { ...@@ -182,7 +182,7 @@ typedef struct ide_pci_device_s {
unsigned short device; unsigned short device;
unsigned int (*init_chipset)(struct pci_dev *dev); unsigned int (*init_chipset)(struct pci_dev *dev);
unsigned int (*ata66_check)(struct ata_channel *hwif); unsigned int (*ata66_check)(struct ata_channel *hwif);
void (*init_hwif)(struct ata_channel *hwif); void (*init_channel)(struct ata_channel *hwif);
void (*dma_init)(struct ata_channel *hwif, unsigned long dmabase); void (*dma_init)(struct ata_channel *hwif, unsigned long dmabase);
ide_pci_enablebit_t enablebits[2]; ide_pci_enablebit_t enablebits[2];
unsigned int bootable; unsigned int bootable;
...@@ -436,24 +436,21 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co ...@@ -436,24 +436,21 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
unsigned long dma_base = 0; unsigned long dma_base = 0;
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
/*
* If we are on the second channel, the dma base address will be one
* entry away from the primary interface.
*/
if (hwif->mate && hwif->mate->dma_base)
dma_base = hwif->mate->dma_base - (hwif->unit ? 0 : 8);
else
dma_base = pci_resource_start(dev, 4); dma_base = pci_resource_start(dev, 4);
if (!dma_base) if (!dma_base)
return 0; return 0;
if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */ /* PDC20246, PDC20262, HPT343, & HPT366 */
if (extra) {
request_region(dma_base + 16, extra, name); request_region(dma_base + 16, extra, name);
dma_base += hwif->unit ? 8 : 0;
hwif->dma_extra = extra; hwif->dma_extra = extra;
}
/* If we are on the second channel, the dma base address will be one
* entry away from the primary interface.
*/
if (hwif->unit == ATA_SECONDARY)
dma_base += 8;
if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) || if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
(dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) || (dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) ||
...@@ -463,8 +460,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co ...@@ -463,8 +460,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
printk(KERN_INFO "%s: simplex device: DMA forced\n", name); printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
} else { } else {
/* /* If the device claims "simplex" DMA, this means only one of
* If the device claims "simplex" DMA, this means only one of
* the two interfaces can be trusted with DMA at any point in * the two interfaces can be trusted with DMA at any point in
* time. So we should enable DMA only on one of the two * time. So we should enable DMA only on one of the two
* interfaces. * interfaces.
...@@ -472,7 +468,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co ...@@ -472,7 +468,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
if ((inb(dma_base + 2) & 0x80)) { if ((inb(dma_base + 2) & 0x80)) {
if ((!hwif->drives[0].present && !hwif->drives[1].present) || if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
(hwif->mate && hwif->mate->dma_base)) { hwif->unit == ATA_SECONDARY) {
printk("%s: simplex device: DMA disabled\n", name); printk("%s: simplex device: DMA disabled\n", name);
dma_base = 0; dma_base = 0;
} }
...@@ -489,8 +485,9 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d ...@@ -489,8 +485,9 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
ide_pci_device_t *d, ide_pci_device_t *d,
int port, int port,
u8 class_rev, u8 class_rev,
int pciirq, struct ata_channel **mate, int pciirq,
int autodma, unsigned short *pcicmd) int autodma,
unsigned short *pcicmd)
{ {
unsigned long dma_base; unsigned long dma_base;
...@@ -503,8 +500,13 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d ...@@ -503,8 +500,13 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80)))) if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
return; return;
dma_base = get_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name); dma_base = get_dma_base(hwif, ((port == ATA_PRIMARY) && d->extra) ? d->extra : 0, dev->name);
if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) { if (!dma_base) {
printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
return;
}
if (!(*pcicmd & PCI_COMMAND_MASTER)) {
/* /*
* Set up BM-DMA capability (PnP BIOS should have done this already) * Set up BM-DMA capability (PnP BIOS should have done this already)
...@@ -517,13 +519,10 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d ...@@ -517,13 +519,10 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
dma_base = 0; dma_base = 0;
} }
} }
if (dma_base) {
if (d->dma_init) if (d->dma_init)
d->dma_init(hwif, dma_base); d->dma_init(hwif, dma_base);
else else
ide_setup_dma(hwif, dma_base, 8); ide_setup_dma(hwif, dma_base, 8);
} else
printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
} }
#endif #endif
...@@ -537,17 +536,16 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -537,17 +536,16 @@ static int __init setup_host_channel(struct pci_dev *dev,
int port, int port,
u8 class_rev, u8 class_rev,
int pciirq, int pciirq,
struct ata_channel **mate,
int autodma, int autodma,
unsigned short *pcicmd) unsigned short *pcicmd)
{ {
unsigned long base = 0; unsigned long base = 0;
unsigned long ctl = 0; unsigned long ctl = 0;
ide_pci_enablebit_t *e = &(d->enablebits[port]); ide_pci_enablebit_t *e = &(d->enablebits[port]);
struct ata_channel *hwif; struct ata_channel *ch;
u8 tmp; u8 tmp;
if (port == 1) { if (port == ATA_SECONDARY) {
/* If this is a Promise FakeRaid controller, the 2nd controller /* If this is a Promise FakeRaid controller, the 2nd controller
* will be marked as disabled while it is actually there and * will be marked as disabled while it is actually there and
...@@ -569,7 +567,7 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -569,7 +567,7 @@ static int __init setup_host_channel(struct pci_dev *dev,
/* Nothing to be done for the second port. /* Nothing to be done for the second port.
*/ */
if (port == 1) { if (port == ATA_SECONDARY) {
if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03)) if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03))
return 0; return 0;
} }
...@@ -599,57 +597,50 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -599,57 +597,50 @@ static int __init setup_host_channel(struct pci_dev *dev,
if (!base) if (!base)
base = port ? 0x170 : 0x1f0; base = port ? 0x170 : 0x1f0;
if ((hwif = lookup_hwif(base, d->bootable, dev->name)) == NULL) if ((ch = lookup_hwif(base, d->bootable, dev->name)) == NULL)
return -ENOMEM; /* no room in ide_hwifs[] */ return -ENOMEM; /* no room in ide_hwifs[] */
if (hwif->io_ports[IDE_DATA_OFFSET] != base) { if (ch->io_ports[IDE_DATA_OFFSET] != base) {
ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); ide_init_hwif_ports(&ch->hw, base, (ctl | 2), NULL);
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
} }
hwif->chipset = ide_pci; ch->chipset = ide_pci;
hwif->pci_dev = dev; ch->pci_dev = dev;
hwif->unit = port; ch->unit = port;
if (!hwif->irq) if (!ch->irq)
hwif->irq = pciirq; ch->irq = pciirq;
/* Setup the mate interface if we have two channels. /* Serialize the interfaces if requested by configuration information.
*/ */
if (*mate) { if (d->flags & ATA_F_SER)
hwif->mate = *mate; ch->serialized = 1;
(*mate)->mate = hwif;
if (d->flags & ATA_F_SER) {
hwif->serialized = 1;
(*mate)->serialized = 1;
}
}
/* Cross wired IRQ lines on UMC chips and no DMA transfers.*/ /* Cross wired IRQ lines on UMC chips and no DMA transfers.*/
if (d->flags & ATA_F_FIXIRQ) { if (d->flags & ATA_F_FIXIRQ) {
hwif->irq = port ? 15 : 14; ch->irq = port ? 15 : 14;
goto no_dma; goto no_dma;
} }
if (d->flags & ATA_F_NODMA) if (d->flags & ATA_F_NODMA)
goto no_dma; goto no_dma;
/* Check whatever this interface is UDMA4 mode capable. */ /* Check whatever this interface is UDMA4 mode capable. */
if (hwif->udma_four) { if (ch->udma_four) {
printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name); printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
} else { } else {
if (d->ata66_check) if (d->ata66_check)
hwif->udma_four = d->ata66_check(hwif); ch->udma_four = d->ata66_check(ch);
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
setup_channel_dma(hwif, dev, d, port, class_rev, pciirq, mate, autodma, pcicmd); setup_channel_dma(ch, dev, d, port, class_rev, pciirq, autodma, pcicmd);
#endif #endif
no_dma: no_dma:
if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ /* Call chipset-specific routine for each enabled channel. */
d->init_hwif(hwif); if (d->init_channel)
d->init_channel(ch);
*mate = hwif;
return 0; return 0;
} }
...@@ -671,7 +662,6 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) ...@@ -671,7 +662,6 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
int pciirq = 0; int pciirq = 0;
unsigned short pcicmd = 0; unsigned short pcicmd = 0;
unsigned short tried_config = 0; unsigned short tried_config = 0;
struct ata_channel *mate = NULL;
unsigned int class_rev; unsigned int class_rev;
#ifdef CONFIG_IDEDMA_AUTO #ifdef CONFIG_IDEDMA_AUTO
...@@ -679,9 +669,9 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) ...@@ -679,9 +669,9 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
autodma = 1; autodma = 1;
#endif #endif
if (d->init_hwif == IDE_NO_DRIVER) { if (d->init_channel == IDE_NO_DRIVER) {
printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name); printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name);
d->init_hwif = NULL; d->init_channel = NULL;
} }
if (pci_enable_device(dev)) { if (pci_enable_device(dev)) {
...@@ -779,8 +769,8 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) ...@@ -779,8 +769,8 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
/* /*
* Set up IDE chanells. First the primary, then the secondary. * Set up IDE chanells. First the primary, then the secondary.
*/ */
setup_host_channel(dev, d, 0, class_rev, pciirq, &mate, autodma, &pcicmd); setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma, &pcicmd);
setup_host_channel(dev, d, 1, class_rev, pciirq, &mate, autodma, &pcicmd); setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd);
} }
static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
...@@ -856,12 +846,6 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic ...@@ -856,12 +846,6 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
if (hpt363_shared_pin && hpt363_shared_irq) { if (hpt363_shared_pin && hpt363_shared_irq) {
d->bootable = ON_BOARD; d->bootable = ON_BOARD;
printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2); printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2);
#if 0
/* I forgot why I did this once, but it fixed something. */
pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
#endif
} }
break; break;
} }
...@@ -894,7 +878,7 @@ static void __init scan_pcidev(struct pci_dev *dev) ...@@ -894,7 +878,7 @@ static void __init scan_pcidev(struct pci_dev *dev)
while (d->vendor && !(d->vendor == vendor && d->device == device)) while (d->vendor && !(d->vendor == vendor && d->device == device))
++d; ++d;
if (d->init_hwif == ATA_PCI_IGNORE) if (d->init_channel == ATA_PCI_IGNORE)
printk("%s: has been ignored by PCI bus scan\n", dev->name); printk("%s: has been ignored by PCI bus scan\n", dev->name);
else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1)) else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1))
return; return;
......
...@@ -16,6 +16,16 @@ ...@@ -16,6 +16,16 @@
* *
* Copyright (c) 1995-1998 Mark Lord * Copyright (c) 1995-1998 Mark Lord
* *
* TODO:
*
* - Find a way to duplicate less code with ide-dma and use the
* dma fileds in the hwif structure instead of our own
* - Fix check_disk_change() call
* - Make module-able (includes setting ppc_md. hooks from within
* this file and not from arch code, and handling module deps with
* mediabay (by having both modules do dynamic lookup of each other
* symbols or by storing hooks at arch level).
*
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -24,26 +34,30 @@ ...@@ -24,26 +34,30 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/pci.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/dbdma.h> #include <asm/dbdma.h>
#include <asm/ide.h> #include <asm/ide.h>
#include <asm/mediabay.h> #include <asm/mediabay.h>
#include <asm/feature.h> #include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/sections.h>
#include <asm/irq.h>
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
#include <linux/adb.h> #include <linux/adb.h>
#include <linux/pmu.h> #include <linux/pmu.h>
#include <asm/irq.h>
#endif #endif
#include "ata-timing.h" #include "ata-timing.h"
extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
extern spinlock_t ide_lock;
#undef IDE_PMAC_DEBUG #undef IDE_PMAC_DEBUG
#define IDE_SYSCLK_NS 30 #define DMA_WAIT_TIMEOUT 500
#define IDE_SYSCLK_ULTRA_PS 0x1d4c /* (15 * 1000 / 2)*/
struct pmac_ide_hwif { struct pmac_ide_hwif {
ide_ioreg_t regbase; ide_ioreg_t regbase;
...@@ -53,11 +67,20 @@ struct pmac_ide_hwif { ...@@ -53,11 +67,20 @@ struct pmac_ide_hwif {
struct device_node* node; struct device_node* node;
u32 timings[2]; u32 timings[2];
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* Those fields are duplicating what is in hwif. We currently
* can't use the hwif ones because of some assumptions that are
* beeing done by the generic code about the kind of dma controller
* and format of the dma table. This will have to be fixed though.
*/
volatile struct dbdma_regs* dma_regs; volatile struct dbdma_regs* dma_regs;
struct dbdma_cmd* dma_table; struct dbdma_cmd* dma_table_cpu;
#endif dma_addr_t dma_table_dma;
struct scatterlist* sg_table;
int sg_nents;
int sg_dma_direction;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
} pmac_ide[MAX_HWIFS]; } pmac_ide[MAX_HWIFS] __pmacdata;
static int pmac_ide_count; static int pmac_ide_count;
...@@ -65,36 +88,160 @@ enum { ...@@ -65,36 +88,160 @@ enum {
controller_ohare, /* OHare based */ controller_ohare, /* OHare based */
controller_heathrow, /* Heathrow/Paddington */ controller_heathrow, /* Heathrow/Paddington */
controller_kl_ata3, /* KeyLargo ATA-3 */ controller_kl_ata3, /* KeyLargo ATA-3 */
controller_kl_ata4 /* KeyLargo ATA-4 */ controller_kl_ata4, /* KeyLargo ATA-4 */
controller_kl_ata4_80 /* KeyLargo ATA-4 with 80 conductor cable */
}; };
/*
* Extra registers, both 32-bit little-endian
*/
#define IDE_TIMING_CONFIG 0x200
#define IDE_INTERRUPT 0x300
/*
* Timing configuration register definitions
*/
/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS)
#define IDE_SYSCLK_NS 30 /* 33Mhz cell */
#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */
/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on
* 40 connector cable and to 4 on 80 connector one.
* Clock unit is 15ns (66Mhz)
*
* 3 Values can be programmed:
* - Write data setup, which appears to match the cycle time. They
* also call it DIOW setup.
* - Ready to pause time (from spec)
* - Address setup. That one is weird. I don't see where exactly
* it fits in UDMA cycles, I got it's name from an obscure piece
* of commented out code in Darwin. They leave it to 0, we do as
* well, despite a comment that would lead to think it has a
* min value of 45ns.
* Apple also add 60ns to the write data setup (or cycle time ?) on
* reads. I can't explain that, I tried it and it broke everything
* here.
*/
#define TR_66_UDMA_MASK 0xfff00000
#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */
#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */
#define TR_66_UDMA_ADDRSETUP_SHIFT 29
#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */
#define TR_66_UDMA_RDY2PAUS_SHIFT 25
#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */
#define TR_66_UDMA_WRDATASETUP_SHIFT 21
#define TR_66_MDMA_MASK 0x000ffc00
#define TR_66_MDMA_RECOVERY_MASK 0x000f8000
#define TR_66_MDMA_RECOVERY_SHIFT 15
#define TR_66_MDMA_ACCESS_MASK 0x00007c00
#define TR_66_MDMA_ACCESS_SHIFT 10
#define TR_66_PIO_MASK 0x000003ff
#define TR_66_PIO_RECOVERY_MASK 0x000003e0
#define TR_66_PIO_RECOVERY_SHIFT 5
#define TR_66_PIO_ACCESS_MASK 0x0000001f
#define TR_66_PIO_ACCESS_SHIFT 0
/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo
* Can do pio & mdma modes, clock unit is 30ns (33Mhz)
*
* The access time and recovery time can be programmed. Some older
* Darwin code base limit OHare to 150ns cycle time. I decided to do
* the same here fore safety against broken old hardware ;)
* The HalfTick bit, when set, adds half a clock (15ns) to the access
* time and removes one from recovery. It's not supported on KeyLargo
* implementation afaik. The E bit appears to be set for PIO mode 0 and
* is used to reach long timings used in this mode.
*/
#define TR_33_MDMA_MASK 0x003ff800
#define TR_33_MDMA_RECOVERY_MASK 0x001f0000
#define TR_33_MDMA_RECOVERY_SHIFT 16
#define TR_33_MDMA_ACCESS_MASK 0x0000f800
#define TR_33_MDMA_ACCESS_SHIFT 11
#define TR_33_MDMA_HALFTICK 0x00200000
#define TR_33_PIO_MASK 0x000007ff
#define TR_33_PIO_E 0x00000400
#define TR_33_PIO_RECOVERY_MASK 0x000003e0
#define TR_33_PIO_RECOVERY_SHIFT 5
#define TR_33_PIO_ACCESS_MASK 0x0000001f
#define TR_33_PIO_ACCESS_SHIFT 0
/*
* Interrupt register definitions
*/
#define IDE_INTR_DMA 0x80000000
#define IDE_INTR_DEVICE 0x40000000
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
# define BAD_DMA_DRIVE 0 # define BAD_DMA_DRIVE 0
# define GOOD_DMA_DRIVE 1 # define GOOD_DMA_DRIVE 1
typedef struct { /* Rounded Multiword DMA timings
*
* I gave up finding a generic formula for all controller
* types and instead, built tables based on timing values
* used by Apple in Darwin's implementation.
*/
struct mdma_timings_t {
int accessTime; int accessTime;
int recoveryTime;
int cycleTime; int cycleTime;
} pmac_ide_timing; };
struct mdma_timings_t mdma_timings_33[] __pmacdata =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
{ 135, 135, 270 },
{ 120, 120, 240 },
{ 105, 105, 210 },
{ 90, 90, 180 },
{ 75, 75, 150 },
{ 75, 45, 120 },
{ 0, 0, 0 }
};
struct mdma_timings_t mdma_timings_33k[] __pmacdata =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
{ 150, 150, 300 },
{ 120, 120, 240 },
{ 90, 120, 210 },
{ 90, 90, 180 },
{ 90, 60, 150 },
{ 90, 30, 120 },
{ 0, 0, 0 }
};
/* Multiword DMA timings */ struct mdma_timings_t mdma_timings_66[] __pmacdata =
static pmac_ide_timing mdma_timings[] =
{ {
{ 215, 480 }, /* Mode 0 */ { 240, 240, 480 },
{ 80, 150 }, /* 1 */ { 180, 180, 360 },
{ 70, 120 } /* 2 */ { 135, 135, 270 },
{ 120, 120, 240 },
{ 105, 105, 210 },
{ 90, 90, 180 },
{ 90, 75, 165 },
{ 75, 45, 120 },
{ 0, 0, 0 }
}; };
/* Ultra DMA timings (for use when I know how to calculate them */ /* Ultra DMA timings (rounded) */
static pmac_ide_timing udma_timings[] = struct {
int addrSetup; /* ??? */
int rdy2pause;
int wrDataSetup;
} udma_timings[] __pmacdata =
{ {
{ 0, 114 }, /* Mode 0 */ { 0, 180, 120 }, /* Mode 0 */
{ 0, 75 }, /* 1 */ { 0, 150, 90 }, /* 1 */
{ 0, 55 }, /* 2 */ { 0, 120, 60 }, /* 2 */
{ 100, 45 }, /* 3 */ { 0, 90, 45 }, /* 3 */
{ 100, 25 } /* 4 */ { 0, 90, 30 } /* 4 */
}; };
/* allow up to 256 DBDMA commands per xfer */ /* allow up to 256 DBDMA commands per xfer */
...@@ -124,7 +271,7 @@ struct pmu_sleep_notifier idepmac_sleep_notifier = { ...@@ -124,7 +271,7 @@ struct pmu_sleep_notifier idepmac_sleep_notifier = {
}; };
#endif /* CONFIG_PMAC_PBOOK */ #endif /* CONFIG_PMAC_PBOOK */
static int static int __pmac
pmac_ide_find(ide_drive_t *drive) pmac_ide_find(ide_drive_t *drive)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -143,7 +290,8 @@ pmac_ide_find(ide_drive_t *drive) ...@@ -143,7 +290,8 @@ pmac_ide_find(ide_drive_t *drive)
* N.B. this can't be an initfunc, because the media-bay task can * N.B. this can't be an initfunc, because the media-bay task can
* call ide_[un]register at any time. * call ide_[un]register at any time.
*/ */
void pmac_ide_init_hwif_ports(hw_regs_t *hw, void __pmac
pmac_ide_init_hwif_ports(hw_regs_t *hw,
ide_ioreg_t data_port, ide_ioreg_t ctrl_port, ide_ioreg_t data_port, ide_ioreg_t ctrl_port,
int *irq) int *irq)
{ {
...@@ -174,7 +322,7 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw, ...@@ -174,7 +322,7 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw,
ide_hwifs[ix].tuneproc = pmac_ide_tuneproc; ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
ide_hwifs[ix].selectproc = pmac_ide_selectproc; ide_hwifs[ix].selectproc = pmac_ide_selectproc;
ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset; ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) { if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) {
ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma) if (!noautodma)
...@@ -201,24 +349,33 @@ pmac_ide_get_devnode(ide_drive_t *drive) ...@@ -201,24 +349,33 @@ pmac_ide_get_devnode(ide_drive_t *drive)
/* Setup timings for the selected drive (master/slave). I still need to verify if this /* Setup timings for the selected drive (master/slave). I still need to verify if this
* is enough, I beleive selectproc will be called whenever an IDE command is started, * is enough, I beleive selectproc will be called whenever an IDE command is started,
* but... */ * but... */
static void static void __pmac
pmac_ide_selectproc(ide_drive_t *drive) pmac_ide_selectproc(ide_drive_t *drive)
{ {
int i = pmac_ide_find(drive); int i = pmac_ide_find(drive);
if (i < 0) if (i < 0)
return; return;
if (drive->select.all & 0x10) if (drive->select.b.unit & 0x01)
out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]); out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[i].timings[1]);
else else
out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]); out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[i].timings[0]);
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
} }
/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
#define SYSCLK_TICKS_UDMA(t) (((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
static __inline__ int /* Note: We don't use the generic routine here because for some
* yet unexplained reasons, it cause some media-bay CD-ROMs to
* lockup the bus. Strangely, this new version of the code is
* almost identical to the generic one and works, I've not yet
* managed to figure out what bit is causing the lockup in the
* generic code, possibly a timing issue...
*
* --BenH
*/
static int __pmac
wait_for_ready(ide_drive_t *drive) wait_for_ready(ide_drive_t *drive)
{ {
/* Timeout bumped for some powerbooks */ /* Timeout bumped for some powerbooks */
...@@ -244,57 +401,80 @@ wait_for_ready(ide_drive_t *drive) ...@@ -244,57 +401,80 @@ wait_for_ready(ide_drive_t *drive)
return 0; return 0;
} }
/* Note: We don't use the generic routine here because some of Apple's static int __pmac
* controller seem to be very sensitive about how things are done.
* We should probably set the NIEN bit, but that's an example of thing
* that can cause the controller to hang under some circumstances when
* done on the media-bay CD-ROM during boot. We do get occasional
* spurrious interrupts because of that.
* --BenH
*/
static int
pmac_ide_do_setfeature(ide_drive_t *drive, byte command) pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
{ {
unsigned long flags;
int result = 1; int result = 1;
unsigned long flags;
struct ata_channel *hwif = HWIF(drive);
save_flags(flags); disable_irq(hwif->irq); /* disable_irq_nosync ?? */
cli();
udelay(1); udelay(1);
SELECT_DRIVE(drive->channel, drive); SELECT_DRIVE(drive->channel, drive);
SELECT_MASK(drive->channel, drive, 0); SELECT_MASK(drive->channel, drive, 0);
udelay(1); udelay(1);
(void)GET_STAT(); /* Get rid of pending error state */
if(wait_for_ready(drive)) { if(wait_for_ready(drive)) {
printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
goto out; goto out;
} }
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); udelay(10);
OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
OUT_BYTE(command, IDE_NSECTOR_REG); OUT_BYTE(command, IDE_NSECTOR_REG);
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
udelay(1); udelay(1);
__save_flags(flags); /* local CPU only */
ide__sti(); /* local CPU only -- for jiffies */
result = wait_for_ready(drive); result = wait_for_ready(drive);
__restore_flags(flags); /* local CPU only */
OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
if (result) if (result)
printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
out: out:
restore_flags(flags); SELECT_MASK(HWIF(drive), drive, 0);
if (result == 0) {
drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
switch(command) {
case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break;
case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break;
case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break;
case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
default: break;
}
}
enable_irq(hwif->irq);
return result; return result;
} }
/* Calculate PIO timings */ /* Calculate PIO timings */
static void static void __pmac
pmac_ide_tuneproc(ide_drive_t *drive, byte pio) pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
{ {
struct ata_timing *t; struct ata_timing *t;
int i; int i;
u32 *timings; u32 *timings;
int accessTicks, recTicks; unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
i = pmac_ide_find(drive); i = pmac_ide_find(drive);
if (i < 0) if (i < 0)
return; return;
if (pio = 255) if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else else
pio = XFER_PIO_0 + min_t(byte, pio, 4); pio = XFER_PIO_0 + min_t(byte, pio, 4);
...@@ -302,27 +482,40 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio) ...@@ -302,27 +482,40 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
t = ata_timing_data(pio); t = ata_timing_data(pio);
accessTicks = SYSCLK_TICKS(t->active); accessTicks = SYSCLK_TICKS(t->active);
if (drive->select.all & 0x10) timings = &pmac_ide[i].timings[drive->select.b.unit & 0x01];
timings = &pmac_ide[i].timings[1];
else recTime = t->cycle - t->active - t->setup;
timings = &pmac_ide[i].timings[0]; recTime = max(recTime, 150U);
accessTime = t->active;
if (pmac_ide[i].kind == controller_kl_ata4) { accessTime = max(accessTime, 150U);
/* The "ata-4" IDE controller of Core99 machines */ if (pmac_ide[i].kind == controller_kl_ata4 ||
accessTicks = SYSCLK_TICKS_UDMA(t->active * 1000); pmac_ide[i].kind == controller_kl_ata4_80) {
recTicks = SYSCLK_TICKS_UDMA(t->cycle * 1000) - accessTicks; /* 66Mhz cell */
accessTicks = SYSCLK_TICKS_66(accessTime);
*timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5); accessTicks = min(accessTicks, 0x1fU);
recTicks = SYSCLK_TICKS_66(recTime);
recTicks = min(recTicks, 0x1fU);
*timings = ((*timings) & ~TR_66_PIO_MASK) |
(accessTicks << TR_66_PIO_ACCESS_SHIFT) |
(recTicks << TR_66_PIO_RECOVERY_SHIFT);
} else { } else {
/* The old "ata-3" IDE controller */ /* 33Mhz cell */
accessTicks = SYSCLK_TICKS(t->active); int ebit = 0;
if (accessTicks < 4) accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = 4; accessTicks = min(accessTicks, 0x1fU);
recTicks = SYSCLK_TICKS(t->cycle) - accessTicks - 4; accessTicks = max(accessTicks, 4U);
if (recTicks < 1) recTicks = SYSCLK_TICKS(recTime);
recTicks = 1; recTicks = min(recTicks, 0x1fU);
recTicks = max(recTicks, 5U) - 4;
*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5); if (recTicks > 9) {
recTicks--; /* guess, but it's only for PIO0, so... */
ebit = 1;
}
*timings = ((*timings) & ~TR_33_PIO_MASK) |
(accessTicks << TR_33_PIO_ACCESS_SHIFT) |
(recTicks << TR_33_PIO_RECOVERY_SHIFT);
if (ebit)
*timings |= TR_33_PIO_E;
} }
#ifdef IDE_PMAC_DEBUG #ifdef IDE_PMAC_DEBUG
...@@ -335,70 +528,134 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio) ...@@ -335,70 +528,134 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
} }
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
static int static int __pmac
set_timings_udma(int intf, u32 *timings, byte speed) set_timings_udma(u32 *timings, byte speed)
{ {
int cycleTime, accessTime; unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
int rdyToPauseTicks, cycleTicks;
if (pmac_ide[intf].kind != controller_kl_ata4)
return 1;
cycleTime = udma_timings[speed & 0xf].cycleTime; rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause);
accessTime = udma_timings[speed & 0xf].accessTime; wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup);
addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup);
rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) |
cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000); (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) |
(rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) |
*timings = ((*timings) & 0xe00fffff) | (addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) |
((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20; TR_66_UDMA_EN;
#ifdef IDE_PMAC_DEBUG
printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n",
speed & 0xf, *timings);
#endif
return 0; return 0;
} }
static int static int __pmac
set_timings_mdma(int intf, u32 *timings, byte speed) set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
{ {
int cycleTime, accessTime; int cycleTime, accessTime, recTime;
int accessTicks, recTicks; unsigned accessTicks, recTicks;
struct mdma_timings_t* tm;
int i;
/* Calculate accesstime and cycle time */ /* Get default cycle time for mode */
cycleTime = mdma_timings[speed & 0xf].cycleTime; switch(speed & 0xf) {
accessTime = mdma_timings[speed & 0xf].accessTime; case 0: cycleTime = 480; break;
if ((pmac_ide[intf].kind == controller_ohare) && (cycleTime < 150)) case 1: cycleTime = 150; break;
case 2: cycleTime = 120; break;
default:
return -1;
}
/* Adjust for drive */
if (drive_cycle_time && drive_cycle_time > cycleTime)
cycleTime = drive_cycle_time;
/* OHare limits according to some old Apple sources */
if ((intf_type == controller_ohare) && (cycleTime < 150))
cycleTime = 150; cycleTime = 150;
/* Get the proper timing array for this controller */
switch(intf_type) {
case controller_kl_ata4:
case controller_kl_ata4_80:
tm = mdma_timings_66;
break;
case controller_kl_ata3:
tm = mdma_timings_33k;
break;
default:
tm = mdma_timings_33;
break;
}
/* Lookup matching access & recovery times */
i = -1;
for (;;) {
if (tm[i+1].cycleTime < cycleTime)
break;
i++;
}
if (i < 0)
return -1;
cycleTime = tm[i].cycleTime;
accessTime = tm[i].accessTime;
recTime = tm[i].recoveryTime;
/* For ata-4 controller */ #ifdef IDE_PMAC_DEBUG
if (pmac_ide[intf].kind == controller_kl_ata4) { printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); cycleTime, accessTime, recTime);
recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks; #endif
*timings = ((*timings) & 0xffe003ff) | if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) {
(accessTicks | (recTicks << 5)) << 10; /* 66Mhz cell */
accessTicks = SYSCLK_TICKS_66(accessTime);
accessTicks = min(accessTicks, 0x1fU);
accessTicks = max(accessTicks, 0x1U);
recTicks = SYSCLK_TICKS_66(recTime);
recTicks = min(recTicks, 0x1fU);
recTicks = max(recTicks, 0x3U);
/* Clear out mdma bits and disable udma */
*timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |
(accessTicks << TR_66_MDMA_ACCESS_SHIFT) |
(recTicks << TR_66_MDMA_RECOVERY_SHIFT);
} else if (intf_type == controller_kl_ata3) {
/* 33Mhz cell on KeyLargo */
accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = max(accessTicks, 1U);
accessTicks = min(accessTicks, 0x1fU);
accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(recTime);
recTicks = max(recTicks, 1U);
recTicks = min(recTicks, 0x1fU);
*timings = ((*timings) & ~TR_33_MDMA_MASK) |
(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
} else { } else {
/* 33Mhz cell on others */
int halfTick = 0; int halfTick = 0;
int origAccessTime = accessTime; int origAccessTime = accessTime;
int origCycleTime = cycleTime; int origRecTime = recTime;
accessTicks = SYSCLK_TICKS(accessTime); accessTicks = SYSCLK_TICKS(accessTime);
if (accessTicks < 1) accessTicks = max(accessTicks, 1U);
accessTicks = 1; accessTicks = min(accessTicks, 0x1fU);
accessTime = accessTicks * IDE_SYSCLK_NS; accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1; recTicks = SYSCLK_TICKS(recTime);
if (recTicks < 1) recTicks = max(recTicks, 2U) - 1;
recTicks = 1; recTicks = min(recTicks, 0x1fU);
cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS; recTime = (recTicks + 1) * IDE_SYSCLK_NS;
if ((accessTicks > 1) &&
/* KeyLargo ata-3 don't support the half-tick stuff */
if ((pmac_ide[intf].kind != controller_kl_ata3) &&
(accessTicks > 1) &&
((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) { ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {
halfTick = 1; halfTick = 1;
accessTicks--; accessTicks--;
} }
*timings = ((*timings) & 0x7FF) | *timings = ((*timings) & ~TR_33_MDMA_MASK) |
(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11; (accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
if (halfTick)
*timings |= TR_33_MDMA_HALFTICK;
} }
#ifdef IDE_PMAC_DEBUG
printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
speed & 0xf, *timings);
#endif
return 0; return 0;
} }
#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
...@@ -406,11 +663,11 @@ set_timings_mdma(int intf, u32 *timings, byte speed) ...@@ -406,11 +663,11 @@ set_timings_mdma(int intf, u32 *timings, byte speed)
/* You may notice we don't use this function on normal operation, /* You may notice we don't use this function on normal operation,
* our, normal mdma function is supposed to be more precise * our, normal mdma function is supposed to be more precise
*/ */
static int static int __pmac
pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
{ {
int intf = pmac_ide_find(drive); int intf = pmac_ide_find(drive);
int unit = (drive->select.all & 0x10) ? 1:0; int unit = (drive->select.b.unit & 0x01);
int ret = 0; int ret = 0;
u32 *timings; u32 *timings;
...@@ -423,19 +680,25 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) ...@@ -423,19 +680,25 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
case XFER_UDMA_4: case XFER_UDMA_4:
case XFER_UDMA_3: case XFER_UDMA_3:
if (pmac_ide[intf].kind != controller_kl_ata4_80)
return 1;
case XFER_UDMA_2: case XFER_UDMA_2:
case XFER_UDMA_1: case XFER_UDMA_1:
case XFER_UDMA_0: case XFER_UDMA_0:
ret = set_timings_udma(intf, timings, speed); if (pmac_ide[intf].kind != controller_kl_ata4 &&
pmac_ide[intf].kind != controller_kl_ata4_80)
return 1;
ret = set_timings_udma(timings, speed);
break; break;
case XFER_MW_DMA_2: case XFER_MW_DMA_2:
case XFER_MW_DMA_1: case XFER_MW_DMA_1:
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0);
break;
case XFER_SW_DMA_2: case XFER_SW_DMA_2:
case XFER_SW_DMA_1: case XFER_SW_DMA_1:
case XFER_SW_DMA_0: case XFER_SW_DMA_0:
ret = set_timings_mdma(intf, timings, speed); return 1;
break;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
case XFER_PIO_4: case XFER_PIO_4:
case XFER_PIO_3: case XFER_PIO_3:
...@@ -460,13 +723,46 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) ...@@ -460,13 +723,46 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
return 0; return 0;
} }
ide_ioreg_t static void __pmac
sanitize_timings(int i)
{
unsigned value;
switch(pmac_ide[i].kind) {
case controller_kl_ata4:
case controller_kl_ata4_80:
value = 0x0008438c;
break;
case controller_kl_ata3:
value = 0x00084526;
break;
case controller_heathrow:
case controller_ohare:
default:
value = 0x00074526;
break;
}
pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value;
}
ide_ioreg_t __pmac
pmac_ide_get_base(int index) pmac_ide_get_base(int index)
{ {
return pmac_ide[index].regbase; return pmac_ide[index].regbase;
} }
int int __pmac
pmac_ide_check_base(ide_ioreg_t base)
{
int ix;
for (ix = 0; ix < MAX_HWIFS; ++ix)
if (base == pmac_ide[ix].regbase)
return ix;
return -1;
}
int __pmac
pmac_ide_get_irq(ide_ioreg_t base) pmac_ide_get_irq(ide_ioreg_t base)
{ {
int ix; int ix;
...@@ -477,7 +773,7 @@ pmac_ide_get_irq(ide_ioreg_t base) ...@@ -477,7 +773,7 @@ pmac_ide_get_irq(ide_ioreg_t base)
return 0; return 0;
} }
static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 };
kdev_t __init kdev_t __init
pmac_find_ide_boot(char *bootdevice, int n) pmac_find_ide_boot(char *bootdevice, int n)
...@@ -494,11 +790,11 @@ pmac_find_ide_boot(char *bootdevice, int n) ...@@ -494,11 +790,11 @@ pmac_find_ide_boot(char *bootdevice, int n)
name = pmac_ide[i].node->full_name; name = pmac_ide[i].node->full_name;
if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
/* XXX should cope with the 2nd drive as well... */ /* XXX should cope with the 2nd drive as well... */
return MKDEV(ide_majors[i], 0); return mk_kdev(ide_majors[i], 0);
} }
} }
return 0; return NODEV;
} }
void __init void __init
...@@ -541,8 +837,11 @@ pmac_ide_probe(void) ...@@ -541,8 +837,11 @@ pmac_ide_probe(void)
for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
struct device_node *tp; struct device_node *tp;
struct pmac_ide_hwif *pmif;
int *bidp; int *bidp;
int in_bay = 0; int in_bay = 0;
u8 pbus, pid;
struct pci_dev *pdev = NULL;
/* /*
* If this node is not under a mac-io or dbdma node, * If this node is not under a mac-io or dbdma node,
...@@ -561,6 +860,15 @@ pmac_ide_probe(void) ...@@ -561,6 +860,15 @@ pmac_ide_probe(void)
continue; continue;
} }
/* We need to find the pci_dev of the mac-io holding the
* IDE interface
*/
if (pci_device_from_OF_node(tp, &pbus, &pid) == 0)
pdev = pci_find_slot(pbus, pid);
if (pdev == NULL)
printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n",
np->full_name);
/* /*
* If this slot is taken (e.g. by ide-pci.c) try the next one. * If this slot is taken (e.g. by ide-pci.c) try the next one.
*/ */
...@@ -569,8 +877,23 @@ pmac_ide_probe(void) ...@@ -569,8 +877,23 @@ pmac_ide_probe(void)
++i; ++i;
if (i >= MAX_HWIFS) if (i >= MAX_HWIFS)
break; break;
pmif = &pmac_ide[i];
base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE; /*
* Some older OFs have bogus sizes, causing request_OF_resource
* to fail. We fix them up here
*/
if (np->addrs[0].size > 0x1000)
np->addrs[0].size = 0x1000;
if (np->n_addrs > 1 && np->addrs[1].size > 0x100)
np->addrs[1].size = 0x100;
if (request_OF_resource(np, 0, " (mac-io IDE IO)") == NULL) {
printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name);
continue;
}
base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE;
/* XXX This is bogus. Should be fixed in the registry by checking /* XXX This is bogus. Should be fixed in the registry by checking
the kind of host interrupt controller, a bit like gatwick the kind of host interrupt controller, a bit like gatwick
...@@ -583,21 +906,30 @@ pmac_ide_probe(void) ...@@ -583,21 +906,30 @@ pmac_ide_probe(void)
} else { } else {
irq = np->intrs[0].line; irq = np->intrs[0].line;
} }
pmac_ide[i].regbase = base; pmif->regbase = base;
pmac_ide[i].irq = irq; pmif->irq = irq;
pmac_ide[i].node = np; pmif->node = np;
if (device_is_compatible(np, "keylargo-ata")) { if (device_is_compatible(np, "keylargo-ata")) {
if (strcmp(np->name, "ata-4") == 0) if (strcmp(np->name, "ata-4") == 0)
pmac_ide[i].kind = controller_kl_ata4; pmif->kind = controller_kl_ata4;
else else
pmac_ide[i].kind = controller_kl_ata3; pmif->kind = controller_kl_ata3;
} else if (device_is_compatible(np, "heathrow-ata")) } else if (device_is_compatible(np, "heathrow-ata"))
pmac_ide[i].kind = controller_heathrow; pmif->kind = controller_heathrow;
else else
pmac_ide[i].kind = controller_ohare; pmif->kind = controller_ohare;
bidp = (int *)get_property(np, "AAPL,bus-id", NULL); bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
pmac_ide[i].aapl_bus_id = bidp ? *bidp : 0; pmif->aapl_bus_id = bidp ? *bidp : 0;
if (pmif->kind == controller_kl_ata4) {
char* cable = get_property(np, "cable-type", NULL);
if (cable && !strncmp(cable, "80-", 3))
pmif->kind = controller_kl_ata4_80;
}
/* Make sure we have sane timings */
sanitize_timings(i);
if (np->parent && np->parent->name if (np->parent && np->parent->name
&& strcasecmp(np->parent->name, "media-bay") == 0) { && strcasecmp(np->parent->name, "media-bay") == 0) {
...@@ -605,39 +937,22 @@ pmac_ide_probe(void) ...@@ -605,39 +937,22 @@ pmac_ide_probe(void)
media_bay_set_ide_infos(np->parent,base,irq,i); media_bay_set_ide_infos(np->parent,base,irq,i);
#endif /* CONFIG_PMAC_PBOOK */ #endif /* CONFIG_PMAC_PBOOK */
in_bay = 1; in_bay = 1;
} else if (pmac_ide[i].kind == controller_ohare) { if (!bidp)
pmif->aapl_bus_id = 1;
} else if (pmif->kind == controller_ohare) {
/* The code below is having trouble on some ohare machines /* The code below is having trouble on some ohare machines
* (timing related ?). Until I can put my hand on one of these * (timing related ?). Until I can put my hand on one of these
* units, I keep the old way * units, I keep the old way
*/ */
feature_set(np, FEATURE_IDE0_enable); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
} else { } else {
/* This is necessary to enable IDE when net-booting */ /* This is necessary to enable IDE when net-booting */
printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n", printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
pmac_ide[i].aapl_bus_id); pmif->aapl_bus_id);
switch(pmac_ide[i].aapl_bus_id) { ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
case 0: ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
feature_set(np, FEATURE_IDE0_reset);
mdelay(10);
feature_set(np, FEATURE_IDE0_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE0_reset);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
mdelay(10); mdelay(10);
feature_set(np, FEATURE_IDE1_enable); ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
mdelay(10);
feature_clear(np, FEATURE_IDE1_reset);
break;
case 2:
/* This one exists only for KL, I don't know
about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
mdelay(10);
feature_clear(np, FEATURE_IDE2_reset);
break;
}
big_delay = 1; big_delay = 1;
} }
...@@ -646,13 +961,15 @@ pmac_ide_probe(void) ...@@ -646,13 +961,15 @@ pmac_ide_probe(void)
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->chipset = ide_pmac; hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;
hwif->udma_four = (pmif->kind == controller_kl_ata4_80);
hwif->pci_dev = pdev;
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
if (in_bay && check_media_bay_by_base(base, MB_CD) == 0) if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)
hwif->noprobe = 0; hwif->noprobe = 0;
#endif /* CONFIG_PMAC_PBOOK */ #endif /* CONFIG_PMAC_PBOOK */
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
if (np->n_addrs >= 2) { if (pdev && np->n_addrs >= 2) {
/* has a DBDMA controller channel */ /* has a DBDMA controller channel */
pmac_ide_setup_dma(np, i); pmac_ide_setup_dma(np, i);
} }
...@@ -674,7 +991,15 @@ pmac_ide_probe(void) ...@@ -674,7 +991,15 @@ pmac_ide_probe(void)
static void __init static void __init
pmac_ide_setup_dma(struct device_node *np, int ix) pmac_ide_setup_dma(struct device_node *np, int ix)
{ {
pmac_ide[ix].dma_regs = struct pmac_ide_hwif *pmif = &pmac_ide[ix];
if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) {
printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n",
np->name);
return;
}
pmif->dma_regs =
(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200); (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
/* /*
...@@ -682,14 +1007,24 @@ pmac_ide_setup_dma(struct device_node *np, int ix) ...@@ -682,14 +1007,24 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
* The +2 is +1 for the stop command and +1 to allow for * The +2 is +1 for the stop command and +1 to allow for
* aligning the start address to a multiple of 16 bytes. * aligning the start address to a multiple of 16 bytes.
*/ */
pmac_ide[ix].dma_table = (struct dbdma_cmd*) pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL); ide_hwifs[ix].pci_dev,
if (pmac_ide[ix].dma_table == 0) { (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
&pmif->dma_table_dma);
if (pmif->dma_table_cpu == NULL) {
printk(KERN_ERR "%s: unable to allocate DMA command list\n", printk(KERN_ERR "%s: unable to allocate DMA command list\n",
ide_hwifs[ix].name); ide_hwifs[ix].name);
return; return;
} }
pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS,
GFP_KERNEL);
if (pmif->sg_table == NULL) {
pci_free_consistent( ide_hwifs[ix].pci_dev,
(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
pmif->dma_table_cpu, pmif->dma_table_dma);
return;
}
ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma) if (!noautodma)
...@@ -697,6 +1032,62 @@ pmac_ide_setup_dma(struct device_node *np, int ix) ...@@ -697,6 +1032,62 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
#endif #endif
} }
static int
pmac_ide_build_sglist (int ix, struct request *rq)
{
struct ata_channel *hwif = &ide_hwifs[ix];
struct pmac_ide_hwif *pmif = &pmac_ide[ix];
request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
struct scatterlist *sg = pmif->sg_table;
int nents;
nents = blk_rq_map_sg(q, rq, pmif->sg_table);
if (rq->q && nents > rq->nr_phys_segments)
printk("ide-pmac: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
if (rq_data_dir(rq) == READ)
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
else
pmif->sg_dma_direction = PCI_DMA_TODEVICE;
return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
}
static int
pmac_ide_raw_build_sglist (int ix, struct request *rq)
{
struct ata_channel *hwif = &ide_hwifs[ix];
struct pmac_ide_hwif *pmif = &pmac_ide[ix];
struct scatterlist *sg = pmif->sg_table;
int nents = 0;
ide_task_t *args = rq->special;
unsigned char *virt_addr = rq->buffer;
int sector_count = rq->nr_sectors;
if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
pmif->sg_dma_direction = PCI_DMA_TODEVICE;
else
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
if (sector_count > 128) {
memset(&sg[nents], 0, sizeof(*sg));
sg[nents].page = virt_to_page(virt_addr);
sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = 128 * SECTOR_SIZE;
nents++;
virt_addr = virt_addr + (128 * SECTOR_SIZE);
sector_count -= 128;
}
memset(&sg[nents], 0, sizeof(*sg));
sg[nents].page = virt_to_page(virt_addr);
sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = sector_count * SECTOR_SIZE;
nents++;
return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
}
/* /*
* pmac_ide_build_dmatable builds the DBDMA command list * pmac_ide_build_dmatable builds the DBDMA command list
* for a transfer and sets the DBDMA channel to point to it. * for a transfer and sets the DBDMA channel to point to it.
...@@ -704,47 +1095,40 @@ pmac_ide_setup_dma(struct device_node *np, int ix) ...@@ -704,47 +1095,40 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
static int static int
pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
{ {
struct dbdma_cmd *table, *tstart; struct dbdma_cmd *table;
int count = 0; int i, count = 0;
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
struct buffer_head *bh = rq->bh;
unsigned int size, addr;
volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs; volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
struct scatterlist *sg;
/* DMA table is already aligned */
table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu;
table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table); /* Make sure DMA controller is stopped (necessary ?) */
out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
while (in_le32(&dma->status) & RUN) while (in_le32(&dma->status) & RUN)
udelay(1); udelay(1);
do { /* Build sglist */
/* if (rq->flags & REQ_DRIVE_TASKFILE) {
* Determine addr and size of next buffer area. We assume that pmac_ide[ix].sg_nents = i = pmac_ide_raw_build_sglist(ix, rq);
* individual virtual buffers are always composed linearly in
* physical memory. For example, we assume that any 8kB buffer
* is always composed of two adjacent physical 4kB pages rather
* than two possibly non-adjacent physical 4kB pages.
*/
if (bh == NULL) { /* paging requests have (rq->bh == NULL) */
addr = virt_to_bus(rq->buffer);
size = rq->nr_sectors << 9;
} else { } else {
/* group sequential buffers into one large buffer */ pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq);
addr = virt_to_bus(bh->b_data);
size = bh->b_size;
while ((bh = bh->b_reqnext) != NULL) {
if ((addr + size) != virt_to_bus(bh->b_data))
break;
size += bh->b_size;
}
} }
if (!i)
return 0;
/* /* Build DBDMA commands list */
* Fill in the next DBDMA command block. sg = pmac_ide[ix].sg_table;
* Note that one DBDMA command can transfer while (i) {
* at most 65535 bytes. u32 cur_addr;
*/ u32 cur_len;
while (size) {
unsigned int tc = (size < 0xfe00)? size: 0xfe00; cur_addr = sg_dma_address(sg);
cur_len = sg_dma_len(sg);
while (cur_len) {
unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
if (++count >= MAX_DCMDS) { if (++count >= MAX_DCMDS) {
printk(KERN_WARNING "%s: DMA table too small\n", printk(KERN_WARNING "%s: DMA table too small\n",
...@@ -753,15 +1137,17 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) ...@@ -753,15 +1137,17 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
} }
st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
st_le16(&table->req_count, tc); st_le16(&table->req_count, tc);
st_le32(&table->phy_addr, addr); st_le32(&table->phy_addr, cur_addr);
table->cmd_dep = 0; table->cmd_dep = 0;
table->xfer_status = 0; table->xfer_status = 0;
table->res_count = 0; table->res_count = 0;
addr += tc; cur_addr += tc;
size -= tc; cur_len -= tc;
++table; ++table;
} }
} while (bh != NULL); sg++;
i--;
}
/* convert the last command to an input/output last command */ /* convert the last command to an input/output last command */
if (count) if (count)
...@@ -773,10 +1159,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) ...@@ -773,10 +1159,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
memset(table, 0, sizeof(struct dbdma_cmd)); memset(table, 0, sizeof(struct dbdma_cmd));
out_le16(&table->command, DBDMA_STOP); out_le16(&table->command, DBDMA_STOP);
out_le32(&dma->cmdptr, virt_to_bus(tstart)); out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma);
return 1; return 1;
} }
/* Teardown mappings after DMA has completed. */
static void
pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
struct scatterlist *sg = pmac_ide[ix].sg_table;
int nents = pmac_ide[ix].sg_nents;
if (nents) {
pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction);
pmac_ide[ix].sg_nents = 0;
}
}
static __inline__ unsigned char static __inline__ unsigned char
dma_bits_to_command(unsigned char bits) dma_bits_to_command(unsigned char bits)
...@@ -791,12 +1191,14 @@ dma_bits_to_command(unsigned char bits) ...@@ -791,12 +1191,14 @@ dma_bits_to_command(unsigned char bits)
} }
static __inline__ unsigned char static __inline__ unsigned char
udma_bits_to_command(unsigned char bits) udma_bits_to_command(unsigned char bits, int high_speed)
{ {
if (high_speed) {
if(bits & 0x10) if(bits & 0x10)
return XFER_UDMA_4; return XFER_UDMA_4;
if(bits & 0x08) if(bits & 0x08)
return XFER_UDMA_3; return XFER_UDMA_3;
}
if(bits & 0x04) if(bits & 0x04)
return XFER_UDMA_2; return XFER_UDMA_2;
if(bits & 0x02) if(bits & 0x02)
...@@ -807,14 +1209,13 @@ udma_bits_to_command(unsigned char bits) ...@@ -807,14 +1209,13 @@ udma_bits_to_command(unsigned char bits)
} }
/* Calculate MultiWord DMA timings */ /* Calculate MultiWord DMA timings */
static int static int __pmac
pmac_ide_mdma_enable(ide_drive_t *drive, int idx) pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
{ {
byte bits = drive->id->dma_mword & 0x07; byte bits = drive->id->dma_mword & 0x07;
byte feature = dma_bits_to_command(bits); byte feature = dma_bits_to_command(bits);
u32 *timings; u32 *timings;
int cycleTime, accessTime; int drive_cycle_time;
int accessTicks, recTicks;
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
int ret; int ret;
...@@ -830,66 +1231,30 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx) ...@@ -830,66 +1231,30 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
drive->init_speed = feature; drive->init_speed = feature;
/* which drive is it ? */ /* which drive is it ? */
if (drive->select.all & 0x10) if (drive->select.b.unit & 0x01)
timings = &pmac_ide[idx].timings[1]; timings = &pmac_ide[idx].timings[1];
else else
timings = &pmac_ide[idx].timings[0]; timings = &pmac_ide[idx].timings[0];
/* Calculate accesstime and cycle time */ /* Check if drive provide explicit cycle time */
cycleTime = mdma_timings[feature & 0xf].cycleTime;
accessTime = mdma_timings[feature & 0xf].accessTime;
if ((id->field_valid & 2) && (id->eide_dma_time)) if ((id->field_valid & 2) && (id->eide_dma_time))
cycleTime = id->eide_dma_time; drive_cycle_time = id->eide_dma_time;
if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150)) else
cycleTime = 150; drive_cycle_time = 0;
/* For ata-4 controller */ /* Calculate controller timings */
if (pmac_ide[idx].kind == controller_kl_ata4) { set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time);
accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
*timings = ((*timings) & 0xffe003ff) |
(accessTicks | (recTicks << 5)) << 10;
} else {
int halfTick = 0;
int origAccessTime = accessTime;
int origCycleTime = cycleTime;
accessTicks = SYSCLK_TICKS(accessTime);
if (accessTicks < 1)
accessTicks = 1;
accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
if (recTicks < 1)
recTicks = 1;
cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
/* KeyLargo ata-3 don't support the half-tick stuff */
if ((pmac_ide[idx].kind != controller_kl_ata3) &&
(accessTicks > 1) &&
((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
halfTick = 1;
accessTicks--;
}
*timings = ((*timings) & 0x7FF) |
(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
}
#ifdef IDE_PMAC_DEBUG
printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
feature & 0xf, *timings);
#endif
drive->current_speed = feature; drive->current_speed = feature;
return 1; return 1;
} }
/* Calculate Ultra DMA timings */ /* Calculate Ultra DMA timings */
static int static int __pmac
pmac_ide_udma_enable(ide_drive_t *drive, int idx) pmac_ide_udma_enable(ide_drive_t *drive, int idx, int high_speed)
{ {
byte bits = drive->id->dma_ultra & 0x1f; byte bits = drive->id->dma_ultra & 0x1f;
byte feature = udma_bits_to_command(bits); byte feature = udma_bits_to_command(bits, high_speed);
int cycleTime, accessTime;
int rdyToPauseTicks, cycleTicks;
u32 *timings; u32 *timings;
int ret; int ret;
...@@ -905,25 +1270,18 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx) ...@@ -905,25 +1270,18 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
drive->init_speed = feature; drive->init_speed = feature;
/* which drive is it ? */ /* which drive is it ? */
if (drive->select.all & 0x10) if (drive->select.b.unit & 0x01)
timings = &pmac_ide[idx].timings[1]; timings = &pmac_ide[idx].timings[1];
else else
timings = &pmac_ide[idx].timings[0]; timings = &pmac_ide[idx].timings[0];
cycleTime = udma_timings[feature & 0xf].cycleTime; set_timings_udma(timings, feature);
accessTime = udma_timings[feature & 0xf].accessTime;
rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
*timings = ((*timings) & 0xe00fffff) |
((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
drive->current_speed = feature; drive->current_speed = feature;
return 1; return 1;
} }
static int static int __pmac
pmac_ide_check_dma(ide_drive_t *drive) pmac_ide_check_dma(ide_drive_t *drive)
{ {
int ata4, udma, idx; int ata4, udma, idx;
...@@ -944,21 +1302,20 @@ pmac_ide_check_dma(ide_drive_t *drive) ...@@ -944,21 +1302,20 @@ pmac_ide_check_dma(ide_drive_t *drive)
enable = 0; enable = 0;
udma = 0; udma = 0;
ata4 = (pmac_ide[idx].kind == controller_kl_ata4); ata4 = (pmac_ide[idx].kind == controller_kl_ata4 ||
pmac_ide[idx].kind == controller_kl_ata4_80);
if(enable) { if(enable) {
if (ata4 && (drive->type == ATA_DISK) && if (ata4 && (drive->type == ATA_DISK) &&
(id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) { (id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) {
/* UltraDMA modes. */ /* UltraDMA modes. */
drive->using_dma = pmac_ide_udma_enable(drive, idx); drive->using_dma = pmac_ide_udma_enable(drive, idx,
pmac_ide[idx].kind == controller_kl_ata4_80);
} }
if (!drive->using_dma && (id->dma_mword & 0x0007)) { if (!drive->using_dma && (id->dma_mword & 0x0007)) {
/* Normal MultiWord DMA modes. */ /* Normal MultiWord DMA modes. */
drive->using_dma = pmac_ide_mdma_enable(drive, idx); drive->using_dma = pmac_ide_mdma_enable(drive, idx);
} }
/* Without this, strange things will happen on Keylargo-based
* machines
*/
OUT_BYTE(0, IDE_CONTROL_REG); OUT_BYTE(0, IDE_CONTROL_REG);
/* Apply settings to controller */ /* Apply settings to controller */
pmac_ide_selectproc(drive); pmac_ide_selectproc(drive);
...@@ -966,10 +1323,25 @@ pmac_ide_check_dma(ide_drive_t *drive) ...@@ -966,10 +1323,25 @@ pmac_ide_check_dma(ide_drive_t *drive)
return 0; return 0;
} }
static void ide_toggle_bounce(ide_drive_t *drive, int on)
{
dma64_addr_t addr = BLK_BOUNCE_HIGH;
if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
if (!PCI_DMA_BUS_IS_PHYS)
addr = BLK_BOUNCE_ANY;
else
addr = HWIF(drive)->pci_dev->dma_mask;
}
blk_queue_bounce_limit(&drive->queue, addr);
}
int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{ {
int ix, dstat, i; int ix, dstat, reading, ata4;
volatile struct dbdma_regs *dma; volatile struct dbdma_regs *dma;
byte unit = (drive->select.b.unit & 0x01);
/* Can we stuff a pointer to our intf structure in config_data /* Can we stuff a pointer to our intf structure in config_data
* or select_data in hwif ? * or select_data in hwif ?
...@@ -978,59 +1350,106 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ...@@ -978,59 +1350,106 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
if (ix < 0) if (ix < 0)
return 0; return 0;
dma = pmac_ide[ix].dma_regs; dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
switch (func) { switch (func) {
case ide_dma_off: case ide_dma_off:
printk(KERN_INFO "%s: DMA disabled\n", drive->name); printk(KERN_INFO "%s: DMA disabled\n", drive->name);
case ide_dma_off_quietly: case ide_dma_off_quietly:
drive->using_dma = 0; drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
break; break;
case ide_dma_on: case ide_dma_on:
case ide_dma_check: case ide_dma_check:
/* Change this to better match ide-dma.c */
pmac_ide_check_dma(drive); pmac_ide_check_dma(drive);
ide_toggle_bounce(drive, drive->using_dma);
break; break;
case ide_dma_read: case ide_dma_read:
case ide_dma_write: case ide_dma_write:
if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write)) /* this almost certainly isn't needed since we don't
appear to have a rwproc */
if (HWIF(drive)->rwproc)
HWIF(drive)->rwproc(drive, func);
reading = (func == ide_dma_read);
if (!pmac_ide_build_dmatable(drive, ix, !reading))
return 1; return 1;
/* Apple adds 60ns to wrDataSetup on reads */
if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[ix].timings[unit] +
((func == ide_dma_read) ? 0x00800000UL : 0));
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
}
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
BUG_ON(HWGROUP(drive)->handler); BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
IDE_COMMAND_REG); (drive->addressing == 1)) {
ide_task_t *args = HWGROUP(drive)->rq->special;
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
} else if (drive->addressing) {
OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
} else {
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
/* fall through */
case ide_dma_begin: case ide_dma_begin:
out_le32(&dma->control, (RUN << 16) | RUN); out_le32(&dma->control, (RUN << 16) | RUN);
/* Make sure it gets to the controller right now */
(void)in_le32(&dma->control);
break; break;
case ide_dma_end: case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
dstat = in_le32(&dma->status); dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
pmac_ide_destroy_dmatable(drive, ix);
/* verify good dma status */ /* verify good dma status */
return (dstat & (RUN|DEAD|ACTIVE)) != RUN; return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
case ide_dma_test_irq: case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN) /* We have to things to deal with here:
return 1; *
/* That's a bit ugly and dangerous, but works in our case * - The dbdma won't stop if the command was started
* to workaround a problem with the channel status staying * but completed with an error without transfering all
* active if the drive returns an error * datas. This happens when bad blocks are met during
* a multi-block transfer.
*
* - The dbdma fifo hasn't yet finished flushing to
* to system memory when the disk interrupt occurs.
*
* The trick here is to increment drive->waiting_for_dma,
* and return as if no interrupt occured. If the counter
* reach a certain timeout value, we then return 1. If
* we really got the interrupt, it will happen right away
* again.
* Apple's solution here may be more elegant. They issue
* a DMA channel interrupt (a separate irq line) via a DBDMA
* NOP command just before the STOP, and wait for both the
* disk and DBDMA interrupts to have completed.
*/ */
if (IDE_CONTROL_REG) {
byte stat; /* If ACTIVE is cleared, the STOP command have passed and
stat = GET_ALTSTAT(); * transfer is complete.
if (stat & ERR_STAT) */
if (!(in_le32(&dma->status) & ACTIVE))
return 1;
if (!drive->waiting_for_dma)
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
called while not waiting\n", ix);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set */
drive->waiting_for_dma++;
if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
printk(KERN_WARNING "ide%d, timeout waiting \
for dbdma command stop\n", ix);
return 1; return 1;
} }
/* In some edge cases, some datas may still be in the dbdma
* engine fifo, we wait a bit for dbdma to complete
*/
while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
if (++i > 100)
return 0;
udelay(1); udelay(1);
} return 0;
return 1;
/* Let's implement tose just in case someone wants them */ /* Let's implement tose just in case someone wants them */
case ide_dma_bad_drive: case ide_dma_bad_drive:
...@@ -1051,7 +1470,6 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ...@@ -1051,7 +1470,6 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
} }
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
#ifdef CONFIG_PMAC_PBOOK
static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base) static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
{ {
int j; int j;
...@@ -1062,7 +1480,9 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base) ...@@ -1062,7 +1480,9 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
switch (drive->type) { switch (drive->type) {
case ATA_DISK: case ATA_DISK:
/* Spin down the drive */ /* Spin down the drive */
outb(0xa0, base+0x60); outb(drive->select.all, base+0x60);
(void)inb(base+0x60);
udelay(100);
outb(0x0, base+0x30); outb(0x0, base+0x30);
outb(0x0, base+0x20); outb(0x0, base+0x20);
outb(0x0, base+0x40); outb(0x0, base+0x40);
...@@ -1086,19 +1506,21 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base) ...@@ -1086,19 +1506,21 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
} }
} }
static void idepmac_wake_device(ide_drive_t *drive, int used_dma) #ifdef CONFIG_PMAC_PBOOK
{ static void __pmac
idepmac_wake_device(ide_drive_t *drive, int used_dma)
{
/* We force the IDE subdriver to check for a media change /* We force the IDE subdriver to check for a media change
* This must be done first or we may lost the condition * This must be done first or we may lost the condition
* *
* Problem: This can schedule. I moved the block device * Problem: This can schedule. I moved the block device
* wakeup almost late by priority because of that. * wakeup almost late by priority because of that.
*/ */
if (DRIVER(drive) && DRIVER(drive)->media_change) if (drive->driver != NULL && ata_ops(drive)->check_media_change)
DRIVER(drive)->media_change(drive); ata_ops(drive)->check_media_change(drive);
/* We kick the VFS too (see fix in ide.c revalidate) */ /* We kick the VFS too (see fix in ide.c revalidate) */
check_disk_change(MKDEV(drive->channel->major, (drive->select.b.unit) << PARTN_BITS)); check_disk_change(mk_kdev(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* We re-enable DMA on the drive if it was active. */ /* We re-enable DMA on the drive if it was active. */
...@@ -1108,15 +1530,16 @@ static void idepmac_wake_device(ide_drive_t *drive, int used_dma) ...@@ -1108,15 +1530,16 @@ static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
*/ */
if (used_dma && !ide_spin_wait_hwgroup(drive)) { if (used_dma && !ide_spin_wait_hwgroup(drive)) {
/* Lock HW group */ /* Lock HW group */
HWGROUP(drive)->busy = 1; set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
pmac_ide_check_dma(drive); pmac_ide_check_dma(drive);
HWGROUP(drive)->busy = 0; clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
spin_unlock_irq(&ide_lock); spin_unlock_irq(&ide_lock);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
} }
static void idepmac_sleep_interface(int i, unsigned base, int mediabay) static void __pmac
idepmac_sleep_interface(int i, unsigned base, int mediabay)
{ {
struct device_node* np = pmac_ide[i].node; struct device_node* np = pmac_ide[i].node;
...@@ -1128,71 +1551,79 @@ static void idepmac_sleep_interface(int i, unsigned base, int mediabay) ...@@ -1128,71 +1551,79 @@ static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
if (mediabay) if (mediabay)
return; return;
/* Disable and reset the bus */ /* Disable the bus */
feature_set(np, FEATURE_IDE0_reset); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0);
feature_clear(np, FEATURE_IDE0_enable);
switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
feature_clear(np, FEATURE_IDE0_enable);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
feature_clear(np, FEATURE_IDE1_enable);
break;
case 2:
feature_set(np, FEATURE_IDE2_reset);
break;
}
} }
static void idepmac_wake_interface(int i, unsigned long base, int mediabay) static void __pmac
idepmac_wake_interface(int i, unsigned long base, int mediabay)
{ {
struct device_node* np = pmac_ide[i].node; struct device_node* np = pmac_ide[i].node;
if (!mediabay) { if (!mediabay) {
/* Revive IDE disk and controller */ /* Revive IDE disk and controller */
switch(pmac_ide[i].aapl_bus_id) { ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1);
case 0: ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1);
feature_set(np, FEATURE_IDE0_reset);
feature_set(np, FEATURE_IOBUS_enable);
mdelay(10);
feature_set(np, FEATURE_IDE0_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE0_reset);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
feature_set(np, FEATURE_IOBUS_enable);
mdelay(10);
feature_set(np, FEATURE_IDE1_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE1_reset);
break;
case 2:
/* This one exists only for KL, I don't know
about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
mdelay(10); mdelay(10);
feature_clear(np, FEATURE_IDE2_reset); ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0);
break;
} }
}
static void
idepmac_sleep_drive(ide_drive_t *drive, int idx, unsigned long base)
{
/* Wait for HW group to complete operations */
if (ide_spin_wait_hwgroup(drive))
// What can we do here ? Wake drive we had already
// put to sleep and return an error ?
return;
else {
/* Lock HW group */
set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
/* Stop the device */
idepmac_sleep_device(drive, idx, base);
spin_unlock_irq(&ide_lock);
} }
}
static void
idepmac_wake_drive(ide_drive_t *drive, unsigned long base)
{
int j;
/* Reset timings */ /* Reset timings */
pmac_ide_selectproc(&ide_hwifs[i].drives[0]); pmac_ide_selectproc(drive);
mdelay(10); mdelay(10);
/* Wait up to 20 seconds for the drive to be ready */
for (j = 0; j < 200; j++) {
int status;
mdelay(100);
outb(drive->select.all, base + 0x60);
if (inb(base + 0x60) != drive->select.all)
continue;
status = inb(base + 0x70);
if (!(status & BUSY_STAT))
break;
}
/* We resume processing on the HW group */
spin_lock_irq(&ide_lock);
clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
if (!list_empty(&drive->queue.queue_head))
do_ide_request(&drive->queue);
spin_unlock_irq(&ide_lock);
} }
/* Note: We support only master drives for now. This will have to be /* Note: We support only master drives for now. This will have to be
* improved if we want to handle sleep on the iMacDV where the CD-ROM * improved if we want to handle sleep on the iMacDV where the CD-ROM
* is a slave * is a slave
*/ */
static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) static int __pmac
idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
{ {
int i, ret; int i, ret;
unsigned long base; unsigned long base;
unsigned long flags;
int big_delay; int big_delay;
switch (when) { switch (when) {
...@@ -1203,34 +1634,19 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) ...@@ -1203,34 +1634,19 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
case PBOOK_SLEEP_NOW: case PBOOK_SLEEP_NOW:
for (i = 0; i < pmac_ide_count; ++i) { for (i = 0; i < pmac_ide_count; ++i) {
struct ata_channel *hwif; struct ata_channel *hwif;
ide_drive_t *drive; int dn;
int unlock = 0;
if ((base = pmac_ide[i].regbase) == 0) if ((base = pmac_ide[i].regbase) == 0)
continue; continue;
hwif = &ide_hwifs[i]; hwif = &ide_hwifs[i];
drive = &hwif->drives[0]; for (dn=0; dn<MAX_DRIVES; dn++) {
if (!hwif->drives[dn].present)
if (drive->present) { continue;
/* Wait for HW group to complete operations */ idepmac_sleep_drive(&hwif->drives[dn], i, base);
if (ide_spin_wait_hwgroup(drive)) {
// What can we do here ? Wake drive we had already
// put to sleep and return an error ?
} else {
unlock = 1;
/* Lock HW group */
HWGROUP(drive)->busy = 1;
/* Stop the device */
idepmac_sleep_device(drive, i, base);
}
} }
/* Disable irq during sleep */ /* Disable irq during sleep */
disable_irq(pmac_ide[i].irq); disable_irq(pmac_ide[i].irq);
if (unlock)
spin_unlock_irq(&ide_lock);
/* Check if this is a media bay with an IDE device or not /* Check if this is a media bay with an IDE device or not
* a media bay. * a media bay.
...@@ -1247,6 +1663,9 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) ...@@ -1247,6 +1663,9 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
if ((base = pmac_ide[i].regbase) == 0) if ((base = pmac_ide[i].regbase) == 0)
continue; continue;
/* Make sure we have sane timings */
sanitize_timings(i);
/* Check if this is a media bay with an IDE device or not /* Check if this is a media bay with an IDE device or not
* a media bay * a media bay
*/ */
...@@ -1263,44 +1682,30 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) ...@@ -1263,44 +1682,30 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
for (i = 0; i < pmac_ide_count; ++i) { for (i = 0; i < pmac_ide_count; ++i) {
struct ata_channel *hwif; struct ata_channel *hwif;
ide_drive_t *drive; int used_dma, dn;
int j, used_dma; int irq_on = 0;
if ((base = pmac_ide[i].regbase) == 0) if ((base = pmac_ide[i].regbase) == 0)
continue; continue;
hwif = &ide_hwifs[i]; hwif = &ide_hwifs[i];
drive = &hwif->drives[0]; for (dn=0; dn<MAX_DRIVES; dn++) {
ide_drive_t *drive = &hwif->drives[dn];
/* Wait for the drive to come up and set it's DMA */ if (!drive->present)
if (drive->present) { continue;
/* Wait up to 20 seconds */
for (j = 0; j < 200; j++) {
int status;
mdelay(100);
status = inb(base + 0x70);
if (!(status & BUSY_STAT))
break;
}
}
/* We don't have re-configured DMA yet */ /* We don't have re-configured DMA yet */
used_dma = drive->using_dma; used_dma = drive->using_dma;
drive->using_dma = 0; drive->using_dma = 0;
idepmac_wake_drive(drive, base);
/* We resume processing on the HW group */ if (!irq_on) {
spin_lock_irqsave(&ide_lock, flags);
enable_irq(pmac_ide[i].irq); enable_irq(pmac_ide[i].irq);
if (drive->present) irq_on = 1;
HWGROUP(drive)->busy = 0; }
spin_unlock_irqrestore(&ide_lock, flags);
/* Wake the device
* We could handle the slave here
*/
if (drive->present)
idepmac_wake_device(drive, used_dma); idepmac_wake_device(drive, used_dma);
} }
if (!irq_on)
enable_irq(pmac_ide[i].irq);
}
break; break;
} }
return PBOOK_SLEEP_OK; return PBOOK_SLEEP_OK;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/types.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -140,7 +140,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -140,7 +140,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
/* kludge for Apple PowerBook internal zip */ /* kludge for Apple PowerBook internal zip */
if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
printk ("FLOPPY"); printk ("FLOPPY");
type = ide_floppy; type = ATA_FLOPPY;
break; break;
} }
#endif #endif
...@@ -666,13 +666,12 @@ static int init_irq(struct ata_channel *hwif) ...@@ -666,13 +666,12 @@ static int init_irq(struct ata_channel *hwif)
hwif->sharing_irq = h->sharing_irq = 1; hwif->sharing_irq = h->sharing_irq = 1;
if (hwif->chipset != ide_pci || h->chipset != ide_pci) if (hwif->chipset != ide_pci || h->chipset != ide_pci)
save_match(hwif, h, &match); save_match(hwif, h, &match);
}
if (hwif->serialized) { /* FIXME: This is still confusing. What would
if (hwif->mate && hwif->mate->irq == h->irq) * happen if we match-ed two times?
save_match(hwif, h, &match); */
}
if (h->serialized) { if (hwif->serialized || h->serialized)
if (h->mate && hwif->irq == h->mate->irq)
save_match(hwif, h, &match); save_match(hwif, h, &match);
} }
} }
...@@ -823,12 +822,11 @@ static void init_gendisk(struct ata_channel *hwif) ...@@ -823,12 +822,11 @@ static void init_gendisk(struct ata_channel *hwif)
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80]; char name[80];
ide_add_generic_settings(hwif->drives + unit); ide_add_generic_settings(hwif->drives + unit);
hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit); hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d", sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->unit && hwif->mate) ? hwif->index, hwif->unit, unit, hwif->drives[unit].lun);
hwif->mate->index : hwif->index,
hwif->unit, unit, hwif->drives[unit].lun);
if (hwif->drives[unit].present) if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
} }
......
...@@ -164,19 +164,6 @@ static int proc_ide_read_imodel ...@@ -164,19 +164,6 @@ static int proc_ide_read_imodel
PROC_IDE_READ_RETURN(page,start,off,count,eof,len); PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
} }
static int proc_ide_read_mate
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
struct ata_channel *hwif = data;
int len;
if (hwif && hwif->mate && hwif->mate->present)
len = sprintf(page, "%s\n", hwif->mate->name);
else
len = sprintf(page, "(none)\n");
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
static int proc_ide_read_channel static int proc_ide_read_channel
(char *page, char **start, off_t off, int count, int *eof, void *data) (char *page, char **start, off_t off, int count, int *eof, void *data)
{ {
...@@ -493,7 +480,6 @@ void destroy_proc_ide_drives(struct ata_channel *hwif) ...@@ -493,7 +480,6 @@ void destroy_proc_ide_drives(struct ata_channel *hwif)
static ide_proc_entry_t hwif_entries[] = { static ide_proc_entry_t hwif_entries[] = {
{ "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL },
{ "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL },
{ "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL },
{ NULL, 0, NULL, NULL } { NULL, 0, NULL, NULL }
}; };
......
...@@ -2177,7 +2177,7 @@ int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp) ...@@ -2177,7 +2177,7 @@ int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
} }
for (h = 0; h < MAX_HWIFS; ++h) { for (h = 0; h < MAX_HWIFS; ++h) {
hwif = &ide_hwifs[h]; hwif = &ide_hwifs[h];
if ((!hwif->present && !hwif->mate && !initializing) || if ((!hwif->present && (hwif->unit == ATA_PRIMARY) && !initializing) ||
(!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found; goto found;
} }
...@@ -3052,9 +3052,13 @@ int __init ide_setup (char *s) ...@@ -3052,9 +3052,13 @@ int __init ide_setup (char *s)
goto done; goto done;
case -2: /* "serialize" */ case -2: /* "serialize" */
do_serialize: do_serialize:
hwif->mate = &ide_hwifs[hw^1]; {
hwif->mate->mate = hwif; struct ata_channel *mate;
hwif->serialized = hwif->mate->serialized = 1;
mate = &ide_hwifs[hw ^ 1];
hwif->serialized = 1;
mate->serialized = 1;
}
goto done; goto done;
case -1: /* "noprobe" */ case -1: /* "noprobe" */
......
...@@ -141,9 +141,19 @@ void __init ide_init_ns87415(struct ata_channel *hwif) ...@@ -141,9 +141,19 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
using_inta = progif & (1 << (hwif->unit << 1)); using_inta = progif & (1 << (hwif->unit << 1));
if (!using_inta) if (!using_inta)
using_inta = ctrl & (1 << (4 + hwif->unit)); using_inta = ctrl & (1 << (4 + hwif->unit));
if (hwif->mate) { if (hwif->unit == ATA_SECONDARY) {
hwif->select_data = hwif->mate->select_data;
/* FIXME: If we are initializing the secondary channel, let us
* assume that the primary channel got initialized just a tad
* bit before now. It would be much cleaner if the data in
* ns87415_control just got duplicated.
*/
if (!hwif->select_data)
hwif->select_data = (unsigned long)
&ns87415_control[ns87415_count - 1];
} else { } else {
if (!hwif->select_data)
hwif->select_data = (unsigned long) hwif->select_data = (unsigned long)
&ns87415_control[ns87415_count++]; &ns87415_control[ns87415_count++];
ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */
...@@ -181,13 +191,23 @@ void __init ide_init_ns87415(struct ata_channel *hwif) ...@@ -181,13 +191,23 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
if (!using_inta) if (!using_inta)
hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */ hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq) else {
hwif->irq = hwif->mate->irq; /* share IRQ with mate */ static int primary_irq = 0;
/* Ugly way to let the primary and secondary channel on the
* chip use the same IRQ line.
*/
if (hwif->unit == ATA_PRIMARY)
primary_irq = hwif->irq;
else if (!hwif->irq)
hwif->irq = primary_irq;
}
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) if (hwif->dma_base)
hwif->dmaproc = &ns87415_dmaproc; hwif->dmaproc = &ns87415_dmaproc;
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif
hwif->selectproc = &ns87415_selectproc; hwif->selectproc = &ns87415_selectproc;
} }
...@@ -224,9 +224,8 @@ int __init setup_pdc4030(struct ata_channel *hwif) ...@@ -224,9 +224,8 @@ int __init setup_pdc4030(struct ata_channel *hwif)
*/ */
hwif->chipset = hwif2->chipset = ide_pdc4030; hwif->chipset = hwif2->chipset = ide_pdc4030;
hwif->mate = hwif2; hwif->unit = ATA_PRIMARY;
hwif2->mate = hwif; hwif2->unit = ATA_SECONDARY;
hwif2->unit = 1;
hwif->selectproc = hwif2->selectproc = &promise_selectproc; hwif->selectproc = hwif2->selectproc = &promise_selectproc;
hwif->serialized = hwif2->serialized = 1; hwif->serialized = hwif2->serialized = 1;
......
/* /*
* $Id: piix.c,v 1.2 2002/03/13 22:50:43 vojtech Exp $ * $Id: piix.c,v 1.3 2002/03/29 16:06:06 vojtech Exp $
* *
* Copyright (c) 2000-2002 Vojtech Pavlik * Copyright (c) 2000-2002 Vojtech Pavlik
* *
...@@ -128,7 +128,7 @@ static int piix_get_info(char *buffer, char **addr, off_t offset, int count) ...@@ -128,7 +128,7 @@ static int piix_get_info(char *buffer, char **addr, off_t offset, int count)
piix_print("----------PIIX BusMastering IDE Configuration---------------"); piix_print("----------PIIX BusMastering IDE Configuration---------------");
piix_print("Driver Version: 1.2"); piix_print("Driver Version: 1.3");
piix_print("South Bridge: %s", bmide_dev->name); piix_print("South Bridge: %s", bmide_dev->name);
pci_read_config_byte(dev, PCI_REVISION_ID, &t); pci_read_config_byte(dev, PCI_REVISION_ID, &t);
...@@ -331,7 +331,7 @@ static int piix_set_drive(ide_drive_t *drive, unsigned char speed) ...@@ -331,7 +331,7 @@ static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
umul = 2; umul = 2;
T = 1000000000 / piix_clock; T = 1000000000 / piix_clock;
UT = T / umul; UT = umul ? (T / umul) : 0;
ata_timing_compute(drive, speed, &t, T, UT); ata_timing_compute(drive, speed, &t, T, UT);
......
...@@ -411,22 +411,23 @@ int __init probe (int base) ...@@ -411,22 +411,23 @@ int __init probe (int base)
return 1; return 1;
} else { } else {
int i,j; int i;
/* secondary enabled */ /* secondary enabled */
printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
ide_hwifs[0].name,ide_hwifs[1].name); ide_hwifs[0].name,ide_hwifs[1].name);
for (i=0;i<2;i++) { for (i = 0; i < 2; i++) {
int j;
ide_hwifs[i].chipset = ide_qd65xx; ide_hwifs[i].chipset = ide_qd65xx;
ide_hwifs[i].mate = &ide_hwifs[i^1];
ide_hwifs[i].unit = i; ide_hwifs[i].unit = i;
ide_hwifs[i].select_data = base; ide_hwifs[i].select_data = base;
ide_hwifs[i].config_data = config | (control <<8); ide_hwifs[i].config_data = config | (control <<8);
ide_hwifs[i].tuneproc = &qd6580_tune_drive; ide_hwifs[i].tuneproc = &qd6580_tune_drive;
for (j=0;j<2;j++) { for (j = 0; j < 2; j++) {
ide_hwifs[i].drives[j].drive_data = ide_hwifs[i].drives[j].drive_data =
i?QD6580_DEF_DATA2:QD6580_DEF_DATA; i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
ide_hwifs[i].drives[j].io_32bit = 1; ide_hwifs[i].drives[j].io_32bit = 1;
......
/* /*
* linux/drivers/ide/sis5513.c Version 0.13 March 4, 2002 * linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002
* *
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
* *
*/ *
* Thanks :
/* Thanks : *
* For direct support and hardware : SiS Taiwan. * SiS Taiwan : for direct support and hardware.
* For ATA100 support advice : Daniela Engert. * Daniela Engert : for initial ATA100 advices and numerous others.
* For checking code correctness, providing patches : * John Fremlin, Manfred Spraul :
* John Fremlin, Manfred Spraul * for checking code correctness, providing patches.
*/ */
/* /*
...@@ -52,59 +52,40 @@ ...@@ -52,59 +52,40 @@
#include "ata-timing.h" #include "ata-timing.h"
/* When DEBUG is defined it outputs initial PCI config register
values and changes made to them by the driver */
// #define DEBUG // #define DEBUG
/* if BROKEN_LEVEL is defined it limits the DMA mode /* When BROKEN_LEVEL is defined it limits the DMA mode
at boot time to its value */ at boot time to its value */
// #define BROKEN_LEVEL XFER_SW_DMA_0 // #define BROKEN_LEVEL XFER_SW_DMA_0
#define DISPLAY_SIS_TIMINGS #define DISPLAY_SIS_TIMINGS
/* Miscellaneaous flags */ /* Miscellaneaous flags */
#define SIS5513_LATENCY 0x01 #define SIS5513_LATENCY 0x01
/* ATA transfer mode capabilities */
/* registers layout and init values are chipset family dependant */
/* 1/ define families */
#define ATA_00 0x00 #define ATA_00 0x00
#define ATA_16 0x01 #define ATA_16 0x01
#define ATA_33 0x02 #define ATA_33 0x02
#define ATA_66 0x03 #define ATA_66 0x03
#define ATA_100a 0x04 #define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout
#define ATA_100 0x05 #define ATA_100 0x05
#define ATA_133 0x06 #define ATA_133 0x06
static unsigned char dma_capability = 0x00; /* 2/ variable holding the controller chipset family value */
static unsigned char chipset_family;
/* /*
* Debug code: following IDE config registers' changes * Debug code: following IDE config registers' changes
*/ */
#ifdef DEBUG #ifdef DEBUG
/* Copy of IDE Config registers 0x00 -> 0x58 /* Copy of IDE Config registers 0x00 -> 0x57
Fewer might be used depending on the actual chipset */ Fewer might be used depending on the actual chipset */
static unsigned char ide_regs_copy[] = { static unsigned char ide_regs_copy[0x58];
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0
};
static byte sis5513_max_config_register(void) { static byte sis5513_max_config_register(void) {
switch(dma_capability) { switch(chipset_family) {
case ATA_00: case ATA_00:
case ATA_16: return 0x4f; case ATA_16: return 0x4f;
case ATA_33: return 0x52; case ATA_33: return 0x52;
...@@ -185,7 +166,7 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) { ...@@ -185,7 +166,7 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
static const struct { static const struct {
const char *name; const char *name;
unsigned short host_id; unsigned short host_id;
unsigned char dma_capability; unsigned char chipset_family;
unsigned char flags; unsigned char flags;
} SiSHostChipInfo[] = { } SiSHostChipInfo[] = {
{ "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, { "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY },
...@@ -211,7 +192,7 @@ static const struct { ...@@ -211,7 +192,7 @@ static const struct {
/* Cycle time bits and values vary accross chip dma capabilities /* Cycle time bits and values vary accross chip dma capabilities
These three arrays hold the register layout and the values to set. These three arrays hold the register layout and the values to set.
Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */ Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
static byte cycle_time_offset[] = {0,0,5,4,4,0,0}; static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
static byte cycle_time_range[] = {0,0,2,3,3,4,4}; static byte cycle_time_range[] = {0,0,2,3,3,4,4};
static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
...@@ -293,13 +274,13 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -293,13 +274,13 @@ static char* get_drives_info (char *buffer, byte pos)
pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11); pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
/* UDMA */ /* UDMA */
if (dma_capability >= ATA_33) { if (chipset_family >= ATA_33) {
p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n",
(reg01 & 0x80) ? "Enabled" : "Disabled", (reg01 & 0x80) ? "Enabled" : "Disabled",
(reg11 & 0x80) ? "Enabled" : "Disabled"); (reg11 & 0x80) ? "Enabled" : "Disabled");
p += sprintf(p, " UDMA Cycle Time "); p += sprintf(p, " UDMA Cycle Time ");
switch(dma_capability) { switch(chipset_family) {
case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
...@@ -308,7 +289,7 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -308,7 +289,7 @@ static char* get_drives_info (char *buffer, byte pos)
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
p += sprintf(p, " \t UDMA Cycle Time "); p += sprintf(p, " \t UDMA Cycle Time ");
switch(dma_capability) { switch(chipset_family) {
case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
...@@ -321,7 +302,7 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -321,7 +302,7 @@ static char* get_drives_info (char *buffer, byte pos)
/* Data Active */ /* Data Active */
p += sprintf(p, " Data Active Time "); p += sprintf(p, " Data Active Time ");
switch(dma_capability) { switch(chipset_family) {
case ATA_00: case ATA_00:
case ATA_16: /* confirmed */ case ATA_16: /* confirmed */
case ATA_33: case ATA_33:
...@@ -332,7 +313,7 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -332,7 +313,7 @@ static char* get_drives_info (char *buffer, byte pos)
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
p += sprintf(p, " \t Data Active Time "); p += sprintf(p, " \t Data Active Time ");
switch(dma_capability) { switch(chipset_family) {
case ATA_00: case ATA_00:
case ATA_16: case ATA_16:
case ATA_33: case ATA_33:
...@@ -370,7 +351,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -370,7 +351,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
u16 reg2, reg3; u16 reg2, reg3;
p += sprintf(p, "\nSiS 5513 "); p += sprintf(p, "\nSiS 5513 ");
switch(dma_capability) { switch(chipset_family) {
case ATA_00: p += sprintf(p, "Unknown???"); break; case ATA_00: p += sprintf(p, "Unknown???"); break;
case ATA_16: p += sprintf(p, "DMA 16"); break; case ATA_16: p += sprintf(p, "DMA 16"); break;
case ATA_33: p += sprintf(p, "Ultra 33"); break; case ATA_33: p += sprintf(p, "Ultra 33"); break;
...@@ -386,7 +367,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -386,7 +367,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
/* Status */ /* Status */
pci_read_config_byte(bmide_dev, 0x4a, &reg); pci_read_config_byte(bmide_dev, 0x4a, &reg);
p += sprintf(p, "Channel Status: "); p += sprintf(p, "Channel Status: ");
if (dma_capability < ATA_66) { if (chipset_family < ATA_66) {
p += sprintf(p, "%s \t \t \t \t %s\n", p += sprintf(p, "%s \t \t \t \t %s\n",
(reg & 0x04) ? "On" : "Off", (reg & 0x04) ? "On" : "Off",
(reg & 0x02) ? "On" : "Off"); (reg & 0x02) ? "On" : "Off");
...@@ -403,7 +384,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -403,7 +384,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
(reg & 0x04) ? "Native" : "Compatible"); (reg & 0x04) ? "Native" : "Compatible");
/* 80-pin cable ? */ /* 80-pin cable ? */
if (dma_capability > ATA_33) { if (chipset_family > ATA_33) {
pci_read_config_byte(bmide_dev, 0x48, &reg); pci_read_config_byte(bmide_dev, 0x48, &reg);
p += sprintf(p, "Cable Type: %s \t \t \t %s\n", p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
(reg & 0x10) ? cable_type[1] : cable_type[0], (reg & 0x10) ? cable_type[1] : cable_type[0],
...@@ -507,7 +488,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio) ...@@ -507,7 +488,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
} }
/* register layout changed with newer ATA100 chips */ /* register layout changed with newer ATA100 chips */
if (dma_capability < ATA_100) { if (chipset_family < ATA_100) {
pci_read_config_byte(dev, drive_pci, &test1); pci_read_config_byte(dev, drive_pci, &test1);
pci_read_config_byte(dev, drive_pci+1, &test2); pci_read_config_byte(dev, drive_pci+1, &test2);
...@@ -587,7 +568,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed) ...@@ -587,7 +568,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
pci_read_config_byte(dev, drive_pci+1, &reg); pci_read_config_byte(dev, drive_pci+1, &reg);
/* Disable UDMA bit for non UDMA modes on UDMA chips */ /* Disable UDMA bit for non UDMA modes on UDMA chips */
if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) { if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
reg &= 0x7F; reg &= 0x7F;
pci_write_config_byte(dev, drive_pci+1, reg); pci_write_config_byte(dev, drive_pci+1, reg);
} }
...@@ -604,11 +585,11 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed) ...@@ -604,11 +585,11 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
/* Force the UDMA bit on if we want to use UDMA */ /* Force the UDMA bit on if we want to use UDMA */
reg |= 0x80; reg |= 0x80;
/* clean reg cycle time bits */ /* clean reg cycle time bits */
reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability])) reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
<< cycle_time_offset[dma_capability]); << cycle_time_offset[chipset_family]);
/* set reg cycle time bits */ /* set reg cycle time bits */
reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0] reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
<< cycle_time_offset[dma_capability]; << cycle_time_offset[chipset_family];
pci_write_config_byte(dev, drive_pci+1, reg); pci_write_config_byte(dev, drive_pci+1, reg);
break; break;
case XFER_MW_DMA_2: case XFER_MW_DMA_2:
...@@ -657,17 +638,17 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) ...@@ -657,17 +638,17 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
drive->dn, ultra); drive->dn, ultra);
#endif #endif
if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100a)) if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a))
speed = XFER_UDMA_5; speed = XFER_UDMA_5;
else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66)) else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66))
speed = XFER_UDMA_4; speed = XFER_UDMA_4;
else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66)) else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66))
speed = XFER_UDMA_3; speed = XFER_UDMA_3;
else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33)) else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_2; speed = XFER_UDMA_2;
else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33)) else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_1; speed = XFER_UDMA_1;
else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33)) else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_0; speed = XFER_UDMA_0;
else if (id->dma_mword & 0x0004) else if (id->dma_mword & 0x0004)
speed = XFER_MW_DMA_2; speed = XFER_MW_DMA_2;
...@@ -700,6 +681,8 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -700,6 +681,8 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_dma_action_t dma_func = ide_dma_off_quietly; ide_dma_action_t dma_func = ide_dma_off_quietly;
config_chipset_for_pio(drive, 5);
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) { if (ide_dmaproc(ide_dma_bad_drive, drive)) {
...@@ -764,10 +747,6 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev) ...@@ -764,10 +747,6 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
struct pci_dev *host; struct pci_dev *host;
int i = 0; int i = 0;
#ifdef DEBUG
sis5513_print_registers(dev, "pci_init_sis5513 start");
#endif
/* Find the chip */ /* Find the chip */
for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) { for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) {
host = pci_find_device (PCI_VENDOR_ID_SI, host = pci_find_device (PCI_VENDOR_ID_SI,
...@@ -777,12 +756,16 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev) ...@@ -777,12 +756,16 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
continue; continue;
host_dev = host; host_dev = host;
dma_capability = SiSHostChipInfo[i].dma_capability; chipset_family = SiSHostChipInfo[i].chipset_family;
printk(SiSHostChipInfo[i].name); printk(SiSHostChipInfo[i].name);
printk("\n"); printk("\n");
#ifdef DEBUG
sis5513_print_registers(dev, "pci_init_sis5513 start");
#endif
if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */ byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
} }
} }
...@@ -792,7 +775,7 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev) ...@@ -792,7 +775,7 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
2/ tell old chips to allow per drive IDE timings */ 2/ tell old chips to allow per drive IDE timings */
if (host_dev) { if (host_dev) {
byte reg; byte reg;
switch(dma_capability) { switch(chipset_family) {
case ATA_133: case ATA_133:
case ATA_100: case ATA_100:
/* Set compatibility bit */ /* Set compatibility bit */
...@@ -847,7 +830,7 @@ unsigned int __init ata66_sis5513(struct ata_channel *hwif) ...@@ -847,7 +830,7 @@ unsigned int __init ata66_sis5513(struct ata_channel *hwif)
byte mask = hwif->unit ? 0x20 : 0x10; byte mask = hwif->unit ? 0x20 : 0x10;
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h); pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
if (dma_capability >= ATA_66) { if (chipset_family >= ATA_66) {
ata66 = (reg48h & mask) ? 0 : 1; ata66 = (reg48h & mask) ? 0 : 1;
} }
return ata66; return ata66;
...@@ -866,7 +849,7 @@ void __init ide_init_sis5513(struct ata_channel *hwif) ...@@ -866,7 +849,7 @@ void __init ide_init_sis5513(struct ata_channel *hwif)
if (host_dev) { if (host_dev) {
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_capability > ATA_16) { if (chipset_family > ATA_16) {
hwif->autodma = noautodma ? 0 : 1; hwif->autodma = noautodma ? 0 : 1;
hwif->highmem = 1; hwif->highmem = 1;
hwif->dmaproc = &sis5513_dmaproc; hwif->dmaproc = &sis5513_dmaproc;
......
...@@ -248,8 +248,19 @@ void __init ide_init_trm290(struct ata_channel *hwif) ...@@ -248,8 +248,19 @@ void __init ide_init_trm290(struct ata_channel *hwif)
if ((reg & 0x10)) if ((reg & 0x10))
hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */ hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq) else {
hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */ static int primary_irq = 0;
/* Ugly way to let the primary and secondary channel on the
* chip use the same IRQ line.
*/
if (hwif->unit == ATA_PRIMARY)
primary_irq = hwif->irq;
else if (!hwif->irq)
hwif->irq = primary_irq;
}
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3); ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
......
...@@ -158,7 +158,6 @@ void __init init_umc8672 (void) /* called from ide.c */ ...@@ -158,7 +158,6 @@ void __init init_umc8672 (void) /* called from ide.c */
ide_hwifs[1].chipset = ide_umc8672; ide_hwifs[1].chipset = ide_umc8672;
ide_hwifs[0].tuneproc = &tune_umc; ide_hwifs[0].tuneproc = &tune_umc;
ide_hwifs[1].tuneproc = &tune_umc; ide_hwifs[1].tuneproc = &tune_umc;
ide_hwifs[0].mate = &ide_hwifs[1]; ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].unit = ATA_SECONDARY;
ide_hwifs[1].unit = 1;
} }
...@@ -433,10 +433,10 @@ typedef void (ide_intrproc_t) (ide_drive_t *); ...@@ -433,10 +433,10 @@ typedef void (ide_intrproc_t) (ide_drive_t *);
typedef void (ide_maskproc_t) (ide_drive_t *, int); typedef void (ide_maskproc_t) (ide_drive_t *, int);
typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t); typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
/* enum {
* ide soft-power support ATA_PRIMARY = 0,
*/ ATA_SECONDARY = 1
typedef int (ide_busproc_t) (ide_drive_t *, int); };
struct ata_channel { struct ata_channel {
struct device dev; /* device handle */ struct device dev; /* device handle */
...@@ -467,7 +467,6 @@ struct ata_channel { ...@@ -467,7 +467,6 @@ struct ata_channel {
struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ struct scatterlist *sg_table; /* Scatter-gather list used to build the above */
int sg_nents; /* Current number of entries in it */ int sg_nents; /* Current number of entries in it */
int sg_dma_direction; /* dma transfer direction */ int sg_dma_direction; /* dma transfer direction */
struct ata_channel *mate; /* other hwif from same PCI chip */
unsigned long dma_base; /* base addr for dma ports */ unsigned long dma_base; /* base addr for dma ports */
unsigned dma_extra; /* extra addr for dma ports */ unsigned dma_extra; /* extra addr for dma ports */
unsigned long config_data; /* for use by chipset-specific code */ unsigned long config_data; /* for use by chipset-specific code */
...@@ -480,7 +479,7 @@ struct ata_channel { ...@@ -480,7 +479,7 @@ struct ata_channel {
hwif_chipset_t chipset; /* sub-module for tuning.. */ hwif_chipset_t chipset; /* sub-module for tuning.. */
unsigned noprobe : 1; /* don't probe for this interface */ unsigned noprobe : 1; /* don't probe for this interface */
unsigned present : 1; /* there is a device on this interface */ unsigned present : 1; /* there is a device on this interface */
unsigned serialized : 1; /* serialized operation with mate hwif */ unsigned serialized : 1; /* serialized operation between channels */
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */ unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */ unsigned reset : 1; /* reset after probe */
unsigned autodma : 1; /* automatically try to enable DMA at boot */ unsigned autodma : 1; /* automatically try to enable DMA at boot */
...@@ -490,7 +489,7 @@ struct ata_channel { ...@@ -490,7 +489,7 @@ struct ata_channel {
unsigned long last_time; /* time when previous rq was done */ unsigned long last_time; /* time when previous rq was done */
#endif #endif
byte straight8; /* Alan's straight 8 check */ byte straight8; /* Alan's straight 8 check */
ide_busproc_t *busproc; /* driver soft-power interface */ int (*busproc)(ide_drive_t *, int); /* driver soft-power interface */
byte bus_state; /* power state of the IDE bus */ byte bus_state; /* power state of the IDE bus */
}; };
...@@ -513,7 +512,6 @@ typedef enum { ...@@ -513,7 +512,6 @@ typedef enum {
*/ */
typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *); typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *);
typedef ide_startstop_t (ide_handler_t)(ide_drive_t *); typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
typedef ide_startstop_t (ide_post_handler_t)(ide_drive_t *);
/* /*
* when ide_timer_expiry fires, invoke a handler of this type * when ide_timer_expiry fires, invoke a handler of this type
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment