patch-2.4.19 linux-2.4.19/drivers/ide/ide-dma.c
Next file: linux-2.4.19/drivers/ide/ide-features.c
Previous file: linux-2.4.19/drivers/ide/ide-disk.c
Back to the patch index
Back to the overall index
- Lines: 159
- Date:
Fri Aug 2 17:39:44 2002
- Orig file:
linux-2.4.18/drivers/ide/ide-dma.c
- Orig date:
Sun Sep 9 10:43:02 2001
diff -urN linux-2.4.18/drivers/ide/ide-dma.c linux-2.4.19/drivers/ide/ide-dma.c
@@ -123,6 +123,7 @@
{ "WDC AC11000H" , "ALL" },
{ "WDC AC22100H" , "ALL" },
+ { "WDC AC31000H" , "ALL" },
{ "WDC AC32500H" , "ALL" },
{ "WDC AC33100H" , "ALL" },
{ "WDC AC31600H" , "ALL" },
@@ -282,6 +283,37 @@
return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
}
+static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
+{
+ struct scatterlist *sg = hwif->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->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) ||
+// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT))
+ if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+ else
+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+
+ if (sector_count > 128) {
+ memset(&sg[nents], 0, sizeof(*sg));
+ sg[nents].address = virt_addr;
+ 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].address = virt_addr;
+ sg[nents].length = sector_count * SECTOR_SIZE;
+ nents++;
+
+ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+}
+
/*
* ide_build_dmatable() prepares a dma request.
* Returns 0 if all went okay, returns 1 otherwise.
@@ -299,7 +331,10 @@
int i;
struct scatterlist *sg;
- HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+ if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE)
+ HWIF(drive)->sg_nents = i = ide_raw_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+ else
+ HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
if (!i)
return 0;
@@ -429,7 +464,14 @@
struct hd_driveid *id = drive->id;
if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
- (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
+ (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
+ if ((id->dma_ultra >> 15) & 1) {
+ printk(", UDMA(mode 7)"); /* UDMA BIOS-enabled! */
+ } else {
+ printk(", UDMA(133)"); /* UDMA BIOS-enabled! */
+ }
+ } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
+ (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
if ((id->dma_ultra >> 13) & 1) {
printk(", UDMA(100)"); /* UDMA BIOS-enabled! */
} else if ((id->dma_ultra >> 12) & 1) {
@@ -456,14 +498,24 @@
static int config_drive_for_dma (ide_drive_t *drive)
{
+ int config_allows_dma = 1;
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
- if (id && (id->capability & 1) && hwif->autodma) {
+#ifdef CONFIG_IDEDMA_ONLYDISK
+ if (drive->media != ide_disk)
+ config_allows_dma = 0;
+#endif
+
+ if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) {
/* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive))
return hwif->dmaproc(ide_dma_off, drive);
+ /* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */
+ if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
+ if ((id->dma_ultra & (id->dma_ultra >> 14) & 2))
+ return hwif->dmaproc(ide_dma_on, drive);
/* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */
if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
if ((id->dma_ultra & (id->dma_ultra >> 11) & 7))
@@ -495,7 +547,7 @@
printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
#endif /* DEBUG */
-#if 1
+#if 0
HWGROUP(drive)->expiry = NULL; /* one free ride for now */
#endif
@@ -550,7 +602,7 @@
*/
int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
-// ide_hwgroup_t *hwgroup = HWGROUP(drive);
+// ide_hwgroup_t *hwgroup = HWGROUP(drive);
ide_hwif_t *hwif = HWIF(drive);
unsigned long dma_base = hwif->dma_base;
byte unit = (drive->select.b.unit & 0x01);
@@ -582,11 +634,20 @@
if (drive->media != ide_disk)
return 0;
#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
- ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
+ ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */
#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
- OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+ if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) &&
+ (drive->addressing == 1)) {
+ ide_task_t *args = HWGROUP(drive)->rq->special;
+ OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], 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);
+ }
+ return HWIF(drive)->dmaproc(ide_dma_begin, drive);
case ide_dma_begin:
/* Note that this is done *after* the cmd has
* been issued to the drive, as per the BM-IDE spec.
@@ -604,7 +665,7 @@
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2);
-#if 0 /* do not set unless you know what you are doing */
+#if 0 /* do not set unless you know what you are doing */
if (dma_stat & 4) {
byte stat = GET_STAT();
outb(dma_base+2, dma_stat & 0xE4);
@@ -649,6 +710,8 @@
GET_STAT(), dma_stat);
return restart_request(drive); // BUG: return types do not match!!
+//#else
+// return HWGROUP(drive)->handler(drive);
#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
case ide_dma_retune:
case ide_dma_lostirq:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)