#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/ioc4_common.h>
#include <asm/io.h>
#include <linux/ide.h>
return intr_reg & 3;
}
-static int
-sgiioc4_ide_dma_begin(ide_drive_t * drive)
+static void sgiioc4_ide_dma_start(ide_drive_t * drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
unsigned int temp_reg = reg | IOC4_S_DMA_START;
hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
-
- return 0;
}
static u32
return 0;
}
-static int
-sgiioc4_ide_dma_verbose(ide_drive_t * drive)
-{
- if (drive->using_dma == 1)
- printk(", UDMA(16)");
- else
- printk(", PIO");
-
- return 1;
-}
-
static int
sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
{
}
/* Creates a dma map for the scatter-gather list entries */
-static void __init
+static void __devinit
ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
{
int num_ports = sizeof (ioc4_dma_regs_t);
if (!hwif->dmatable_cpu)
goto dma_alloc_failure;
- hwif->sg_table =
- kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL);
-
- if (!hwif->sg_table)
- goto dma_sgalloc_failure;
+ hwif->sg_max_nents = IOC4_PRD_ENTRIES;
hwif->dma_base2 = (unsigned long)
pci_alloc_consistent(hwif->pci_dev,
return;
dma_base2alloc_failure:
- kfree(hwif->sg_table);
-
-dma_sgalloc_failure:
pci_free_consistent(hwif->pci_dev,
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
hwif->dmatable_cpu, hwif->dmatable_dma);
unsigned int count = 0, i = 1;
struct scatterlist *sg;
- if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
- hwif->sg_nents = i = ide_raw_build_sglist(drive, rq);
- else
- hwif->sg_nents = i = ide_build_sglist(drive, rq);
+ hwif->sg_nents = i = ide_build_sglist(drive, rq);
if (!i)
return 0; /* sglist of length Zero */
return 0; /* revert to PIO for this request */
}
-static int
-sgiioc4_ide_dma_read(ide_drive_t * drive)
+static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
unsigned int count = 0;
+ int ddir;
- if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) {
- /* try PIO instead of DMA */
- return 1;
- }
- /* Writes FROM the IOC4 TO Main Memory */
- sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive);
-
- return 0;
-}
-
-static int
-sgiioc4_ide_dma_write(ide_drive_t * drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- unsigned int count = 0;
+ if (rq_data_dir(rq))
+ ddir = PCI_DMA_TODEVICE;
+ else
+ ddir = PCI_DMA_FROMDEVICE;
- if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) {
+ if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) {
/* try PIO instead of DMA */
+ ide_map_sg(drive, rq);
return 1;
}
- sgiioc4_configure_for_dma(IOC4_DMA_READ, drive);
- /* Writes TO the IOC4 FROM Main Memory */
+ if (rq_data_dir(rq))
+ /* Writes TO the IOC4 FROM Main Memory */
+ ddir = IOC4_DMA_READ;
+ else
+ /* Writes FROM the IOC4 TO Main Memory */
+ ddir = IOC4_DMA_WRITE;
+
+ sgiioc4_configure_for_dma(ddir, drive);
return 0;
}
-static void __init
+static void __devinit
ide_init_sgiioc4(ide_hwif_t * hwif)
{
hwif->mmio = 2;
hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
hwif->mwdma_mask = 0x2; /* Multimode-2 DMA */
hwif->swdma_mask = 0x2;
- hwif->identify = NULL;
hwif->tuneproc = NULL; /* Sets timing for PIO mode */
hwif->speedproc = NULL; /* Sets timing for DMA &/or PIO modes */
hwif->selectproc = NULL;/* Use the default routine to select drive */
hwif->quirkproc = NULL;
hwif->busproc = NULL;
- hwif->ide_dma_read = &sgiioc4_ide_dma_read;
- hwif->ide_dma_write = &sgiioc4_ide_dma_write;
- hwif->ide_dma_begin = &sgiioc4_ide_dma_begin;
+ hwif->dma_setup = &sgiioc4_ide_dma_setup;
+ hwif->dma_start = &sgiioc4_ide_dma_start;
hwif->ide_dma_end = &sgiioc4_ide_dma_end;
hwif->ide_dma_check = &sgiioc4_ide_dma_check;
hwif->ide_dma_on = &sgiioc4_ide_dma_on;
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
- hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose;
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
hwif->INB = &sgiioc4_INB;
}
-static int __init
+static int __devinit
sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
{
unsigned long base, ctl, dma_base, irqport;
printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
hwif->name, d->name);
- probe_hwif_init(hwif);
+ if (probe_hwif_init(hwif))
+ return -EIO;
/* Create /proc/ide entries */
create_proc_ide_interfaces();
return 0;
}
-/* This ensures that we can build this for generic kernels without
- * having all the SN2 code sync'd and merged.
- */
-typedef enum pciio_endian_e {
- PCIDMA_ENDIAN_BIG,
- PCIDMA_ENDIAN_LITTLE
-} pciio_endian_t;
-pciio_endian_t snia_pciio_endian_set(struct pci_dev
- *pci_dev, pciio_endian_t device_end,
- pciio_endian_t desired_end);
-
-static unsigned int __init
+static unsigned int __devinit
pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
{
unsigned int class_rev;
- pciio_endian_t endian_status;
-
- if (pci_enable_device(dev)) {
- printk(KERN_ERR
- "Failed to enable device %s at slot %s\n",
- d->name, dev->slot_name);
- return -ENODEV;
- }
- pci_set_master(dev);
+ int ret;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
- d->name, dev->slot_name, class_rev);
+ d->name, pci_name(dev), class_rev);
if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
"firmware is obsolete - please upgrade to revision"
- "46 or higher\n", d->name, dev->slot_name);
- return -ENODEV;
- }
-
- /* Enable Byte Swapping in the PIC... */
- endian_status = snia_pciio_endian_set(dev, PCIDMA_ENDIAN_LITTLE,
- PCIDMA_ENDIAN_BIG);
- if (endian_status != PCIDMA_ENDIAN_BIG) {
- printk(KERN_ERR
- "Failed to set endianness for device %s at slot %s\n",
- d->name, dev->slot_name);
- return -ENODEV;
+ "46 or higher\n", d->name, pci_name(dev));
+ ret = -EAGAIN;
+ goto out;
}
-
- return sgiioc4_ide_setup_pci_device(dev, d);
+ ret = sgiioc4_ide_setup_pci_device(dev, d);
+out:
+ return ret;
}
static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
}
};
-static int __devinit
-sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
- return 0;
-}
-
-static struct pci_device_id sgiioc4_pci_tbl[] = {
- {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
- PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0},
- {0}
-};
-MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
-
-static struct pci_driver driver = {
- .name = "SGI-IOC4_IDE",
- .id_table = sgiioc4_pci_tbl,
- .probe = sgiioc4_init_one,
-};
-
-static int
-sgiioc4_ide_init(void)
+int
+ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_pci_register_driver(&driver);
+ return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
}
-module_init(sgiioc4_ide_init);
MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_ide_attach_one);