Commit 96a878c0 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] IDE 58

 - m68k fixes by Roman Zippel.

 - CDROM PIO mode fix by Osamu Tamita.
   (You are true "Hawk-eye" hovering over my head! Respect - and many Thanks.)

 - Virtualize the udma_enable method as well to help ARM and PPC people.  Please
   please if you would like to have some other methods virtualized in a similar
   way - just tell me or even better do it yourself at the end of ide-dma.c.
   I *don't mind* patches.

 - Fix the pmac code to adhere to the new API. It's supposed to work again.
   However this is blind coding... I give myself 80% chances for it to work ;-).
parent 682a9c41
...@@ -103,7 +103,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -103,7 +103,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
fi fi
if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_mbool ' Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL dep_mbool ' Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL
fi fi
if [ "$CONFIG_ATARI" = "y" ]; then if [ "$CONFIG_ATARI" = "y" ]; then
dep_bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI dep_bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI
......
/* /*
* linux/drivers/ide/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver * linux/drivers/ide/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
* *
* Copyright (C) 1997 by Geert Uytterhoeven * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
* *
* This driver was written by based on the specifications in README.buddha and * This driver was written based on the specifications in README.buddha and
* the X-Surf info from Inside_XSurf.txt available at * the X-Surf info from Inside_XSurf.txt available at
* http://www.jschoenfeld.com * http://www.jschoenfeld.com
* *
...@@ -52,7 +52,7 @@ static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { ...@@ -52,7 +52,7 @@ static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
}; };
static const u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = { static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
XSURF_BASE1, XSURF_BASE2 XSURF_BASE1, XSURF_BASE2
}; };
...@@ -97,7 +97,7 @@ static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { ...@@ -97,7 +97,7 @@ static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
}; };
static const int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
XSURF_IRQ1, XSURF_IRQ2 XSURF_IRQ1, XSURF_IRQ2
}; };
...@@ -108,8 +108,9 @@ static const int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { ...@@ -108,8 +108,9 @@ static const int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
* Board information * Board information
*/ */
enum BuddhaType_Enum {BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF}; typedef enum BuddhaType_Enum {
typedef enum BuddhaType_Enum BuddhaType; BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
} BuddhaType;
/* /*
...@@ -175,15 +176,20 @@ void __init buddha_init(void) ...@@ -175,15 +176,20 @@ void __init buddha_init(void)
if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE")) if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE"))
continue; continue;
if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE")) if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE"))
goto fail_base2;
if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) {
release_mem_region(board+XSURF_BASE2, 0x1000);
fail_base2:
release_mem_region(board+XSURF_BASE1, 0x1000);
continue; continue;
if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) }
continue;
} }
buddha_board = ZTWO_VADDR(board); buddha_board = ZTWO_VADDR(board);
/* write to BUDDHA_IRQ_MR to enable the board IRQ */ /* write to BUDDHA_IRQ_MR to enable the board IRQ */
/* X-Surf doesn't have this. IRQs are always on */ /* X-Surf doesn't have this. IRQs are always on */
if(type != BOARD_XSURF) *(char *)(buddha_board+BUDDHA_IRQ_MR) = 0; if (type != BOARD_XSURF)
z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
for(i=0;i<buddha_num_hwifs;i++) { for(i=0;i<buddha_num_hwifs;i++) {
if(type != BOARD_XSURF) { if(type != BOARD_XSURF) {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* License. See the file COPYING in the main directory of this archive for * License. See the file COPYING in the main directory of this archive for
* more details. * more details.
*/ */
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
......
...@@ -962,7 +962,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request ...@@ -962,7 +962,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
/* First, figure out if we need to bit-bucket /* First, figure out if we need to bit-bucket
any of the leading sectors. */ any of the leading sectors. */
nskip = MIN(rq->current_nr_sectors - bio_sectors(rq->bio), sectors_to_transfer); nskip = MIN((int)(rq->current_nr_sectors - bio_sectors(rq->bio)), sectors_to_transfer);
while (nskip > 0) { while (nskip > 0) {
/* We need to throw away a sector. */ /* We need to throw away a sector. */
......
...@@ -533,8 +533,20 @@ void udma_enable(struct ata_device *drive, int on, int verbose) ...@@ -533,8 +533,20 @@ void udma_enable(struct ata_device *drive, int on, int verbose)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
int set_high = 1; int set_high = 1;
u8 unit = (drive->select.b.unit & 0x01); u8 unit;
u64 addr = BLK_BOUNCE_HIGH; u64 addr;
/* Method overloaded by host chip specific code. */
if (ch->udma_enable) {
ch->udma_enable(drive, on, verbose);
return;
}
/* Fall back to the default implementation. */
unit = (drive->select.b.unit & 0x01);
addr = BLK_BOUNCE_HIGH;
if (!on) { if (!on) {
if (verbose) if (verbose)
......
...@@ -256,7 +256,15 @@ struct { ...@@ -256,7 +256,15 @@ struct {
#define IDE_WAKEUP_DELAY_MS 2000 #define IDE_WAKEUP_DELAY_MS 2000
static void pmac_ide_setup_dma(struct device_node *np, int ix); static void pmac_ide_setup_dma(struct device_node *np, int ix);
static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq);
static void pmac_udma_enable(struct ata_device *drive, int on, int verbose);
static int pmac_udma_start(struct ata_device *drive, struct request *rq);
static int pmac_udma_stop(struct ata_device *drive);
static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq);
static int pmac_udma_read(struct ata_device *drive, struct request *rq);
static int pmac_udma_write(struct ata_device *drive, struct request *rq);
static int pmac_udma_irq_status(struct ata_device *drive);
static int pmac_ide_dmaproc(struct ata_device *drive);
static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr); static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr);
static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed); static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed);
static void pmac_ide_tuneproc(struct ata_device *drive, byte pio); static void pmac_ide_tuneproc(struct ata_device *drive, byte pio);
...@@ -323,7 +331,13 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, ...@@ -323,7 +331,13 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
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_cpu) { if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) {
ide_hwifs[ix].udma = pmac_ide_dmaproc; ide_hwifs[ix].udma_enable = pmac_udma_enable;
ide_hwifs[ix].udma_start = pmac_udma_start;
ide_hwifs[ix].udma_stop = pmac_udma_stop;
ide_hwifs[ix].udma_read = pmac_udma_read;
ide_hwifs[ix].udma_write = pmac_udma_write;
ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status;
ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma) if (!noautodma)
ide_hwifs[ix].autodma = 1; ide_hwifs[ix].autodma = 1;
...@@ -1025,7 +1039,13 @@ pmac_ide_setup_dma(struct device_node *np, int ix) ...@@ -1025,7 +1039,13 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
pmif->dma_table_cpu, pmif->dma_table_dma); pmif->dma_table_cpu, pmif->dma_table_dma);
return; return;
} }
ide_hwifs[ix].udma = pmac_ide_dmaproc; ide_hwifs[ix].udma_enable = pmac_udma_enable;
ide_hwifs[ix].udma_start = pmac_udma_start;
ide_hwifs[ix].udma_stop = pmac_udma_stop;
ide_hwifs[ix].udma_read = pmac_udma_read;
ide_hwifs[ix].udma_write = pmac_udma_write;
ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status;
ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma) if (!noautodma)
ide_hwifs[ix].autodma = 1; ide_hwifs[ix].autodma = 1;
...@@ -1336,9 +1356,63 @@ static void ide_toggle_bounce(ide_drive_t *drive, int on) ...@@ -1336,9 +1356,63 @@ static void ide_toggle_bounce(ide_drive_t *drive, int on)
blk_queue_bounce_limit(&drive->queue, addr); blk_queue_bounce_limit(&drive->queue, addr);
} }
static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static void pmac_udma_enable(struct ata_device *drive, int on, int verbose)
{
if (verbose) {
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
}
drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
}
static int pmac_udma_start(struct ata_device *drive, struct request *rq)
{
int ix, ata4;
volatile struct dbdma_regs *dma;
/* Can we stuff a pointer to our intf structure in config_data
* or select_data in hwif ?
*/
ix = pmac_ide_find(drive);
if (ix < 0)
return 0;
dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
out_le32(&dma->control, (RUN << 16) | RUN);
/* Make sure it gets to the controller right now */
(void)in_le32(&dma->control);
return 0;
}
static int pmac_udma_stop(struct ata_device *drive)
{
int ix, dstat, ata4;
volatile struct dbdma_regs *dma;
/* Can we stuff a pointer to our intf structure in config_data
* or select_data in hwif ?
*/
ix = pmac_ide_find(drive);
if (ix < 0)
return 0;
dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
drive->waiting_for_dma = 0;
dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
pmac_ide_destroy_dmatable(drive->channel, ix);
/* verify good dma status */
return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
}
static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq)
{ {
int ix, dstat, reading, ata4; int ix, ata4;
volatile struct dbdma_regs *dma; volatile struct dbdma_regs *dma;
byte unit = (drive->select.b.unit & 0x01); byte unit = (drive->select.b.unit & 0x01);
...@@ -1352,29 +1426,13 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1352,29 +1426,13 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80); pmac_ide[ix].kind == controller_kl_ata4_80);
switch (func) {
case ide_dma_off:
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
case ide_dma_off_quietly:
drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
break;
case ide_dma_on:
case ide_dma_check:
/* Change this to better match ide-dma.c */
pmac_ide_check_dma(drive);
ide_toggle_bounce(drive, drive->using_dma);
break;
case ide_dma_read:
case ide_dma_write:
reading = (func == ide_dma_read);
if (!pmac_ide_build_dmatable(drive, rq, ix, !reading)) if (!pmac_ide_build_dmatable(drive, rq, ix, !reading))
return 1; return 1;
/* Apple adds 60ns to wrDataSetup on reads */ /* Apple adds 60ns to wrDataSetup on reads */
if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) { if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[ix].timings[unit] + pmac_ide[ix].timings[unit] +
((func == ide_dma_read) ? 0x00800000UL : 0)); ((reading) ? 0x00800000UL : 0));
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE)); (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
} }
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
...@@ -1390,39 +1448,54 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1390,39 +1448,54 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
} else { } else {
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
} }
/* fall through */
case ide_dma_begin: return udma_start(drive, rq);
out_le32(&dma->control, (RUN << 16) | RUN); }
/* Make sure it gets to the controller right now */
(void)in_le32(&dma->control); static int pmac_udma_read(struct ata_device *drive, struct request *rq)
break; {
case ide_dma_end: /* returns 1 on error, 0 otherwise */ return pmac_do_udma(1, drive, rq);
drive->waiting_for_dma = 0; }
dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); static int pmac_udma_write(struct ata_device *drive, struct request *rq)
pmac_ide_destroy_dmatable(drive->channel, ix); {
/* verify good dma status */ return pmac_do_udma(0, drive, rq);
return (dstat & (RUN|DEAD|ACTIVE)) != RUN; }
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
/*
* FIXME: This should be attached to a channel as we can see now!
*/
static int pmac_udma_irq_status(struct ata_device *drive)
{
int ix, ata4;
volatile struct dbdma_regs *dma;
/* Can we stuff a pointer to our intf structure in config_data
* or select_data in hwif ?
*/
ix = pmac_ide_find(drive);
if (ix < 0)
return 0;
dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
/* We have to things to deal with here: /* We have to things to deal with here:
* *
* - The dbdma won't stop if the command was started * - The dbdma won't stop if the command was started but completed with
* but completed with an error without transfering all * an error without transfering all datas. This happens when bad blocks
* datas. This happens when bad blocks are met during * are met during a multi-block transfer.
* a multi-block transfer.
* *
* - The dbdma fifo hasn't yet finished flushing to * - The dbdma fifo hasn't yet finished flushing to to system memory
* to system memory when the disk interrupt occurs. * when the disk interrupt occurs.
* *
* The trick here is to increment drive->waiting_for_dma, * The trick here is to increment drive->waiting_for_dma, and return as
* and return as if no interrupt occured. If the counter * if no interrupt occured. If the counter reach a certain timeout
* reach a certain timeout value, we then return 1. If * value, we then return 1. If we really got the interrupt, it will
* we really got the interrupt, it will happen right away * happen right away again. Apple's solution here may be more elegant.
* again. * They issue a DMA channel interrupt (a separate irq line) via a DBDMA
* Apple's solution here may be more elegant. They issue * NOP command just before the STOP, and wait for both the disk and
* a DMA channel interrupt (a separate irq line) via a DBDMA * DBDMA interrupts to have completed.
* NOP command just before the STOP, and wait for both the
* disk and DBDMA interrupts to have completed.
*/ */
/* If ACTIVE is cleared, the STOP command have passed and /* If ACTIVE is cleared, the STOP command have passed and
...@@ -1444,22 +1517,17 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1444,22 +1517,17 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
} }
udelay(1); udelay(1);
return 0; return 0;
}
static int pmac_ide_dmaproc(struct ata_device *drive)
{
/* Change this to better match ide-dma.c */
pmac_ide_check_dma(drive);
ide_toggle_bounce(drive, drive->using_dma);
/* Let's implement tose just in case someone wants them */
case ide_dma_bad_drive:
case ide_dma_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive));
case ide_dma_lostirq:
case ide_dma_timeout:
printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported func only: %d\n", func);
return 1;
default:
printk(KERN_WARNING "ide_pmac_dmaproc: unsupported func: %d\n", func);
return 1;
}
return 0; return 0;
} }
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #endif
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)
{ {
......
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#define DTF(x...) #define DTF(x...)
#endif #endif
#define SUPPORT_VLB_SYNC 1
/* /*
* for now, taskfile requests are special :/ * for now, taskfile requests are special :/
*/ */
......
...@@ -2097,6 +2097,7 @@ void ide_unregister(struct ata_channel *ch) ...@@ -2097,6 +2097,7 @@ void ide_unregister(struct ata_channel *ch)
ch->atapi_read = old.atapi_read; ch->atapi_read = old.atapi_read;
ch->atapi_write = old.atapi_write; ch->atapi_write = old.atapi_write;
ch->XXX_udma = old.XXX_udma; ch->XXX_udma = old.XXX_udma;
ch->udma_enable = old.udma_enable;
ch->udma_start = old.udma_start; ch->udma_start = old.udma_start;
ch->udma_stop = old.udma_stop; ch->udma_stop = old.udma_stop;
ch->udma_read = old.udma_read; ch->udma_read = old.udma_read;
......
...@@ -121,6 +121,7 @@ static __inline__ void ide_init_default_hwifs(void) ...@@ -121,6 +121,7 @@ static __inline__ void ide_init_default_hwifs(void)
#define inb(p) in_8(ADDR_TRANS_B(p)) #define inb(p) in_8(ADDR_TRANS_B(p))
#define inb_p(p) in_8(ADDR_TRANS_B(p)) #define inb_p(p) in_8(ADDR_TRANS_B(p))
#define inw(p) in_be16(ADDR_TRANS_W(p)) #define inw(p) in_be16(ADDR_TRANS_W(p))
#define inw_p(p) in_be16(ADDR_TRANS_W(p))
#define outb(v,p) out_8(ADDR_TRANS_B(p),v) #define outb(v,p) out_8(ADDR_TRANS_B(p),v)
#define outb_p(v,p) out_8(ADDR_TRANS_B(p),v) #define outb_p(v,p) out_8(ADDR_TRANS_B(p),v)
#define outw(v,p) out_be16(ADDR_TRANS_W(p),v) #define outw(v,p) out_be16(ADDR_TRANS_W(p),v)
......
...@@ -459,6 +459,8 @@ struct ata_channel { ...@@ -459,6 +459,8 @@ struct ata_channel {
int (*XXX_udma)(struct ata_device *); int (*XXX_udma)(struct ata_device *);
void (*udma_enable)(struct ata_device *, int, int);
int (*udma_start) (struct ata_device *, struct request *rq); int (*udma_start) (struct ata_device *, struct request *rq);
int (*udma_stop) (struct ata_device *); int (*udma_stop) (struct ata_device *);
......
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