Commit 056cc252 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] Update powermac IDE driver

This updates the powermac IDE driver in 2.5 so it uses the 2.5 kernel
interfaces and types rather than the 2.4 ones.  It also makes it use
blk_rq_map_sg rather than its own code to set up scatter/gather lists in
pmac_ide_build_sglist, and makes it use ide_lock instead of
io_request_lock.
parent 594c9846
...@@ -717,11 +717,11 @@ pmac_find_ide_boot(char *bootdevice, int n) ...@@ -717,11 +717,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
...@@ -932,47 +932,32 @@ pmac_ide_probe(void) ...@@ -932,47 +932,32 @@ pmac_ide_probe(void)
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
static int static int
pmac_ide_build_sglist(ide_hwif_t *hwif, struct request *rq) pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq)
{ {
ide_hwif_t *hwif = HWIF(drive);
pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
struct buffer_head *bh;
struct scatterlist *sg = pmif->sg_table; struct scatterlist *sg = pmif->sg_table;
int nents = 0; int nents;
if (hwif->sg_dma_active) if (hwif->sg_dma_active)
BUG(); BUG();
if (rq->cmd == READ) nents = blk_rq_map_sg(&drive->queue, rq, sg);
if (rq_data_dir(rq) == READ)
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
else else
pmif->sg_dma_direction = PCI_DMA_TODEVICE; pmif->sg_dma_direction = PCI_DMA_TODEVICE;
bh = rq->bh;
do {
unsigned char *virt_addr = bh->b_data;
unsigned int size = bh->b_size;
if (nents >= MAX_DCMDS)
return 0;
while ((bh = bh->b_reqnext) != NULL) {
if ((virt_addr + size) != (unsigned char *) bh->b_data)
break;
size += bh->b_size;
}
memset(&sg[nents], 0, sizeof(*sg));
sg[nents].address = virt_addr;
sg[nents].length = size;
nents++;
} while (bh != NULL);
return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
} }
static int static int
pmac_ide_raw_build_sglist(ide_hwif_t *hwif, struct request *rq) pmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq)
{ {
ide_hwif_t *hwif = HWIF(drive);
pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
struct scatterlist *sg = hwif->sg_table; struct scatterlist *sg = pmif->sg_table;
int nents = 0; int nents = 0;
ide_task_t *args = rq->special; ide_task_t *args = rq->special;
unsigned char *virt_addr = rq->buffer; unsigned char *virt_addr = rq->buffer;
...@@ -983,16 +968,18 @@ pmac_ide_raw_build_sglist(ide_hwif_t *hwif, struct request *rq) ...@@ -983,16 +968,18 @@ pmac_ide_raw_build_sglist(ide_hwif_t *hwif, struct request *rq)
else else
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
if (sector_count > 128) { if (sector_count > 127) {
memset(&sg[nents], 0, sizeof(*sg)); memset(&sg[nents], 0, sizeof(*sg));
sg[nents].address = virt_addr; sg[nents].page = virt_to_page(virt_addr);
sg[nents].length = 128 * SECTOR_SIZE; sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = 127 * SECTOR_SIZE;
nents++; nents++;
virt_addr = virt_addr + (128 * SECTOR_SIZE); virt_addr = virt_addr + (127 * SECTOR_SIZE);
sector_count -= 128; sector_count -= 127;
} }
memset(&sg[nents], 0, sizeof(*sg)); memset(&sg[nents], 0, sizeof(*sg));
sg[nents].address = virt_addr; sg[nents].page = virt_to_page(virt_addr);
sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = sector_count * SECTOR_SIZE; sg[nents].length = sector_count * SECTOR_SIZE;
nents++; nents++;
...@@ -1023,10 +1010,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr) ...@@ -1023,10 +1010,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr)
udelay(1); udelay(1);
/* Build sglist */ /* Build sglist */
if (rq->cmd == IDE_DRIVE_TASKFILE) if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
pmif->sg_nents = i = pmac_ide_raw_build_sglist(hwif, rq); pmif->sg_nents = i = pmac_ide_raw_build_sglist(drive, rq);
else else
pmif->sg_nents = i = pmac_ide_build_sglist(hwif, rq); pmif->sg_nents = i = pmac_ide_build_sglist(drive, rq);
if (!i) if (!i)
return 0; return 0;
...@@ -1045,7 +1032,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr) ...@@ -1045,7 +1032,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr)
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",
drive->name); drive->name);
return 0; /* revert to PIO for this request */ goto use_pio_instead;
} }
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);
...@@ -1062,17 +1049,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr) ...@@ -1062,17 +1049,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int wr)
} }
/* convert the last command to an input/output last command */ /* convert the last command to an input/output last command */
if (count) if (count) {
st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST);
else
printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
/* add the stop command to the end of the list */ /* add the stop command to the end of the list */
memset(table, 0, sizeof(struct dbdma_cmd)); memset(table, 0, sizeof(struct dbdma_cmd));
st_le16(&table->command, DBDMA_STOP); st_le16(&table->command, DBDMA_STOP);
mb(); mb();
writel(pmif->dma_table_dma, &dma->cmdptr); writel(pmif->dma_table_dma, &dma->cmdptr);
return 1; return 1;
}
printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
use_pio_instead:
pci_unmap_sg(hwif->pci_dev,
pmif->sg_table,
pmif->sg_nents,
pmif->sg_dma_direction);
hwif->sg_dma_active = 0;
return 0; /* revert to PIO for this request */
} }
/* Teardown mappings after DMA has completed. */ /* Teardown mappings after DMA has completed. */
...@@ -1279,7 +1273,7 @@ pmac_ide_dma_read (ide_drive_t *drive) ...@@ -1279,7 +1273,7 @@ pmac_ide_dma_read (ide_drive_t *drive)
} }
#else #else
command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
if (rq->cmd == IDE_DRIVE_TASKFILE) { if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special; ide_task_t *args = rq->special;
command = args->tfRegister[IDE_COMMAND_OFFSET]; command = args->tfRegister[IDE_COMMAND_OFFSET];
} }
...@@ -1332,7 +1326,7 @@ pmac_ide_dma_write (ide_drive_t *drive) ...@@ -1332,7 +1326,7 @@ pmac_ide_dma_write (ide_drive_t *drive)
} }
#else #else
command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
if (rq->cmd == IDE_DRIVE_TASKFILE) { if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special; ide_task_t *args = rq->special;
command = args->tfRegister[IDE_COMMAND_OFFSET]; command = args->tfRegister[IDE_COMMAND_OFFSET];
} }
...@@ -1579,8 +1573,8 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma) ...@@ -1579,8 +1573,8 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma)
* 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)) //if (DRIVER(drive))
check_disk_change(MKDEV(drive->disk->major, drive->disk->first_minor)); // check_disk_change(MKDEV(drive->disk->major, drive->disk->first_minor));
#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. */
...@@ -1595,7 +1589,7 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma) ...@@ -1595,7 +1589,7 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma)
HWGROUP(drive)->busy = 0; HWGROUP(drive)->busy = 0;
if (!list_empty(&drive->queue.queue_head)) if (!list_empty(&drive->queue.queue_head))
ide_do_request(HWGROUP(drive), 0); ide_do_request(HWGROUP(drive), 0);
spin_unlock_irq(&io_request_lock); spin_unlock_irq(&ide_lock);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
} }
...@@ -1648,7 +1642,7 @@ idepmac_sleep_drive(ide_drive_t *drive, unsigned long base) ...@@ -1648,7 +1642,7 @@ idepmac_sleep_drive(ide_drive_t *drive, unsigned long base)
idepmac_sleep_device(drive, base); idepmac_sleep_device(drive, base);
} }
if (unlock) if (unlock)
spin_unlock_irq(&io_request_lock); spin_unlock_irq(&ide_lock);
} }
static void static void
...@@ -1675,11 +1669,11 @@ idepmac_wake_drive(ide_drive_t *drive, unsigned long base) ...@@ -1675,11 +1669,11 @@ idepmac_wake_drive(ide_drive_t *drive, unsigned long base)
} }
/* We resume processing on the HW group */ /* We resume processing on the HW group */
spin_lock_irqsave(&io_request_lock, flags); spin_lock_irqsave(&ide_lock, flags);
HWGROUP(drive)->busy = 0; HWGROUP(drive)->busy = 0;
if (!list_empty(&drive->queue.queue_head)) if (!list_empty(&drive->queue.queue_head))
ide_do_request(HWGROUP(drive), 0); ide_do_request(HWGROUP(drive), 0);
spin_unlock_irqrestore(&io_request_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
/* 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
......
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