Commit ab08629c authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.13 IDE 52

Adapted from patch Bar³omiej ¯o³nierkiewicz:

 - make straight8 a flag in ata_channel instead of byte

 - don't store tables as code in drive_is_flashcard()
   and ide_xfer_verbose()

 - fix init_gendisk() (due to 2.5.13 blksize_size[] change)

 - compress region requesting/releasing
   in channel_probe() and ide_unregister()

 - clean a bit ide_setup_ports()

Start of DMA handling tratment.

 - Fix the parameters to ide_build_dmatable() to be channel and request.
   Rename it to udma_new_table(). udma will mark arch specific functions
   later.

 - Let ide_start_dma() take the request directly as an arguemnt. Rename it to
   ata_start_dma(). After realizing that the usage of the func argument of it
   was bogous and that nobody is using rwproc we where able to remove both of
   them.

 - Fix ide_destroy_dmatable() to take the channel as argument and rename it to
   udma_destroy_table(). This function should have possible architecture
   specific implementation as well at some point in time.

 - Split up the TCQ UDMA handling stuff in to proper functions. Jens must has
   been dreaming as he introduced them ;-).
parent 65ae2979
...@@ -191,7 +191,7 @@ unsigned char IN_BYTE(ide_ioreg_t reg) { ...@@ -191,7 +191,7 @@ unsigned char IN_BYTE(ide_ioreg_t reg) {
#define ATA_PIO0_STROBE 19 #define ATA_PIO0_STROBE 19
#define ATA_PIO0_HOLD 4 #define ATA_PIO0_HOLD 4
static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq);
static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive, static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive,
void *buffer, unsigned int length); void *buffer, unsigned int length);
...@@ -278,7 +278,7 @@ init_e100_ide (void) ...@@ -278,7 +278,7 @@ init_e100_ide (void)
hwif->chipset = ide_etrax100; hwif->chipset = ide_etrax100;
hwif->tuneproc = &tune_e100_ide; hwif->tuneproc = &tune_e100_ide;
hwif->dmaproc = &e100_dmaproc; hwif->udma = &e100_dmaproc;
hwif->ata_read = e100_ide_input_data; hwif->ata_read = e100_ide_input_data;
hwif->ata_write = e100_ide_output_data; hwif->ata_write = e100_ide_output_data;
hwif->atapi_read = e100_atapi_read; hwif->atapi_read = e100_atapi_read;
...@@ -564,13 +564,14 @@ e100_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) ...@@ -564,13 +564,14 @@ e100_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS]; static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS];
static unsigned int ata_tot_size; static unsigned int ata_tot_size;
/* /*
* e100_ide_build_dmatable() prepares a dma request. * This prepares a dma request. Returns 0 if all went okay, returns 1
* Returns 0 if all went okay, returns 1 otherwise. * otherwise.
*/ */
static int e100_ide_build_dmatable (ide_drive_t *drive)
static int e100_udma_new_table(struct ata_channel *ch, struct request *rq)
{ {
struct request *rq = HWGROUP(drive)->rq;
struct buffer_head *bh = rq->bh; struct buffer_head *bh = rq->bh;
unsigned long size, addr; unsigned long size, addr;
unsigned int count = 0; unsigned int count = 0;
...@@ -602,7 +603,7 @@ static int e100_ide_build_dmatable (ide_drive_t *drive) ...@@ -602,7 +603,7 @@ static int e100_ide_build_dmatable (ide_drive_t *drive)
/* did we run out of descriptors? */ /* did we run out of descriptors? */
if(count >= MAX_DMA_DESCRS) { if(count >= MAX_DMA_DESCRS) {
printk("%s: too few DMA descriptors\n", drive->name); printk("%s: too few DMA descriptors\n", ch->name);
return 1; return 1;
} }
...@@ -656,7 +657,7 @@ static int e100_ide_build_dmatable (ide_drive_t *drive) ...@@ -656,7 +657,7 @@ static int e100_ide_build_dmatable (ide_drive_t *drive)
return 0; return 0;
} }
printk("%s: empty DMA table?\n", drive->name); printk("%s: empty DMA table?\n", ch->name);
return 1; /* let the PIO routines handle this weirdness */ return 1; /* let the PIO routines handle this weirdness */
} }
...@@ -695,7 +696,7 @@ static ide_startstop_t etrax_dma_intr (struct ata_device *drive, struct request ...@@ -695,7 +696,7 @@ static ide_startstop_t etrax_dma_intr (struct ata_device *drive, struct request
LED_DISK_READ(0); LED_DISK_READ(0);
LED_DISK_WRITE(0); LED_DISK_WRITE(0);
dma_stat = drive->channel->dmaproc(ide_dma_end, drive); dma_stat = drive->channel->udma(ide_dma_end, drive, rq);
stat = GET_STAT(); /* get drive status */ stat = GET_STAT(); /* get drive status */
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) { if (!dma_stat) {
...@@ -726,7 +727,7 @@ static ide_startstop_t etrax_dma_intr (struct ata_device *drive, struct request ...@@ -726,7 +727,7 @@ static ide_startstop_t etrax_dma_intr (struct ata_device *drive, struct request
* the caller should revert to PIO for the current request. * the caller should revert to PIO for the current request.
*/ */
static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive) static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
static unsigned int reading; /* static to support ide_dma_begin semantics */ static unsigned int reading; /* static to support ide_dma_begin semantics */
int atapi = 0; int atapi = 0;
...@@ -786,21 +787,18 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive) ...@@ -786,21 +787,18 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
/* set up the Etrax DMA descriptors */ /* set up the Etrax DMA descriptors */
if(e100_ide_build_dmatable (drive)) if(e100_udma_new_table(drive->channel, rq))
return 1; return 1;
if(!atapi) { if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */ /* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */ /* issue cmd to drive */
OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG); OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG);
} }
/* begin DMA */ /* begin DMA */
*R_DMA_CH3_FIRST = virt_to_phys(ata_descrs); *R_DMA_CH3_FIRST = virt_to_phys(ata_descrs);
*R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
...@@ -829,26 +827,22 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive) ...@@ -829,26 +827,22 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
/* set up the Etrax DMA descriptors */ /* set up the Etrax DMA descriptors */
if(e100_ide_build_dmatable (drive)) if(e100_udma_new_table(drive->channel, rq))
return 1; return 1;
if(!atapi) { if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */ /* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */ /* issue cmd to drive */
OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG); OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG);
} }
/* begin DMA */ /* begin DMA */
*R_DMA_CH2_FIRST = virt_to_phys(ata_descrs); *R_DMA_CH2_FIRST = virt_to_phys(ata_descrs);
*R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start); *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start);
/* initiate a multi word dma write using DMA handshaking */ /* initiate a multi word dma write using DMA handshaking */
*R_ATA_TRANSFER_CNT = *R_ATA_TRANSFER_CNT =
IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
...@@ -878,7 +872,7 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive) ...@@ -878,7 +872,7 @@ static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
* --- Marcin Dalecki * --- Marcin Dalecki
*/ */
void ide_release_dma(struct ata_channel *hwif) void ide_release_dma(struct ata_channel *ch)
{ {
/* empty */ /* empty */
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
O_TARGET := idedriver.o O_TARGET := idedriver.o
export-objs := ide-taskfile.o ide.o ide-features.o ide-probe.o ataraid.o export-objs := ide-taskfile.o ide.o ide-features.o ide-probe.o ide-dma.o ataraid.o
obj-y := obj-y :=
obj-m := obj-m :=
......
...@@ -74,12 +74,12 @@ extern struct ata_timing ata_timing[]; ...@@ -74,12 +74,12 @@ extern struct ata_timing ata_timing[];
* It's a bit elaborate due to the legacy we have to bear. * It's a bit elaborate due to the legacy we have to bear.
*/ */
extern short ata_timing_mode(ide_drive_t *drive, int map); extern short ata_timing_mode(struct ata_device *drive, int map);
extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q, extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q,
int T, int UT); int T, int UT);
extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b,
struct ata_timing *m, unsigned int what); struct ata_timing *m, unsigned int what);
extern struct ata_timing* ata_timing_data(short speed); extern struct ata_timing* ata_timing_data(short speed);
extern int ata_timing_compute(ide_drive_t *drive, extern int ata_timing_compute(struct ata_device *drive,
short speed, struct ata_timing *t, int T, int UT); short speed, struct ata_timing *t, int T, int UT);
#endif #endif
...@@ -208,10 +208,10 @@ static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ...@@ -208,10 +208,10 @@ static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2,
* This routine writes the prepared setup/active/recovery counts * This routine writes the prepared setup/active/recovery counts
* for a drive into the cmd646 chipset registers to active them. * for a drive into the cmd646 chipset registers to active them.
*/ */
static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count) static void program_drive_counts(struct ata_device *drive, int setup_count, int active_count, int recovery_count)
{ {
unsigned long flags; unsigned long flags;
ide_drive_t *drives = drive->channel->drives; struct ata_device *drives = drive->channel->drives;
byte temp_b; byte temp_b;
static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
static const byte recovery_counts[] = static const byte recovery_counts[] =
...@@ -277,7 +277,7 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ ...@@ -277,7 +277,7 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ
* 8: prefetch off, 9: prefetch on, 255: auto-select best mode. * 8: prefetch off, 9: prefetch on, 255: auto-select best mode.
* Called with 255 at boot time. * Called with 255 at boot time.
*/ */
static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted) static void cmd64x_tuneproc(struct ata_device *drive, byte mode_wanted)
{ {
int recovery_time, clock_time; int recovery_time, clock_time;
byte recovery_count2, cycle_count; byte recovery_count2, cycle_count;
...@@ -351,7 +351,7 @@ static byte cmd680_taskfile_timing(struct ata_channel *hwif) ...@@ -351,7 +351,7 @@ static byte cmd680_taskfile_timing(struct ata_channel *hwif)
} }
} }
static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted) static void cmd680_tuneproc(struct ata_device *drive, byte mode_wanted)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
...@@ -381,7 +381,7 @@ static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted) ...@@ -381,7 +381,7 @@ static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted)
pci_write_config_word(dev, drive_pci, speedt); pci_write_config_word(dev, drive_pci, speedt);
} }
static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, byte set_speed) static void config_cmd64x_chipset_for_pio(struct ata_device *drive, byte set_speed)
{ {
byte speed = 0x00; byte speed = 0x00;
byte set_pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; byte set_pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
...@@ -392,7 +392,7 @@ static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, byte set_speed) ...@@ -392,7 +392,7 @@ static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, byte set_speed)
(void) ide_config_drive_speed(drive, speed); (void) ide_config_drive_speed(drive, speed);
} }
static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed) static void config_cmd680_chipset_for_pio(struct ata_device *drive, byte set_speed)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
...@@ -418,7 +418,7 @@ static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed) ...@@ -418,7 +418,7 @@ static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed)
} }
} }
static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) static void config_chipset_for_pio(struct ata_device *drive, byte set_speed)
{ {
if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680) { if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
config_cmd680_chipset_for_pio(drive, set_speed); config_cmd680_chipset_for_pio(drive, set_speed);
...@@ -427,7 +427,7 @@ static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) ...@@ -427,7 +427,7 @@ static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
} }
} }
static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) static int cmd64x_tune_chipset(struct ata_device *drive, byte speed)
{ {
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -496,7 +496,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) ...@@ -496,7 +496,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
return err; return err;
} }
static int cmd680_tune_chipset (ide_drive_t *drive, byte speed) static int cmd680_tune_chipset(struct ata_device *drive, byte speed)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
...@@ -612,7 +612,7 @@ speed_break : ...@@ -612,7 +612,7 @@ speed_break :
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) static int config_cmd64x_chipset_for_dma(struct ata_device *drive, unsigned int rev, byte ultra_66)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -697,7 +697,7 @@ static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, ...@@ -697,7 +697,7 @@ static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev,
return rval; return rval;
} }
static int config_cmd680_chipset_for_dma (ide_drive_t *drive) static int config_cmd680_chipset_for_dma(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
byte udma_66 = eighty_ninty_three(drive); byte udma_66 = eighty_ninty_three(drive);
...@@ -739,14 +739,14 @@ static int config_cmd680_chipset_for_dma (ide_drive_t *drive) ...@@ -739,14 +739,14 @@ static int config_cmd680_chipset_for_dma (ide_drive_t *drive)
return rval; return rval;
} }
static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) static int config_chipset_for_dma(struct ata_device *drive, unsigned int rev, byte ultra_66)
{ {
if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680) if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680)
return (config_cmd680_chipset_for_dma(drive)); return (config_cmd680_chipset_for_dma(drive));
return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66)); return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66));
} }
static int cmd64x_config_drive_for_dma (ide_drive_t *drive) static int cmd64x_config_drive_for_dma(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -839,11 +839,12 @@ static int cmd680_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -839,11 +839,12 @@ static int cmd680_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
byte dma_stat = 0; struct ata_channel *ch = drive->channel;
byte dma_alt_stat = 0; u8 dma_stat = 0;
byte mask = (drive->channel->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; u8 dma_alt_stat = 0;
unsigned long dma_base = drive->channel->dma_base; u8 mask = (ch->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
struct pci_dev *dev = drive->channel->pci_dev; unsigned long dma_base = ch->dma_base;
struct pci_dev *dev = ch->pci_dev;
byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
switch (func) { switch (func) {
...@@ -856,8 +857,8 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -856,8 +857,8 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
if (jack_slap) { if (jack_slap) {
byte dma_intr = 0; byte dma_intr = 0;
byte dma_mask = (drive->channel->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; byte dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
byte dma_reg = (drive->channel->unit) ? ARTTIM2 : CFR; byte dma_reg = (ch->unit) ? ARTTIM2 : CFR;
(void) pci_read_config_byte(dev, dma_reg, &dma_intr); (void) pci_read_config_byte(dev, dma_reg, &dma_intr);
/* /*
* DAMN BMIDE is not connected to PCI space! * DAMN BMIDE is not connected to PCI space!
...@@ -866,7 +867,7 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -866,7 +867,7 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
*/ */
(void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */ (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */
} }
ide_destroy_dmatable(drive); /* purge DMA mappings */ udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2); dma_stat = inb(dma_base+2);
...@@ -891,8 +892,8 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -891,8 +892,8 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
*/ */
static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
unsigned long dma_base = hwif->dma_base; unsigned long dma_base = ch->dma_base;
byte dma_stat; byte dma_stat;
switch (func) { switch (func) {
...@@ -903,7 +904,7 @@ static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -903,7 +904,7 @@ static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
dma_stat = inb(dma_base+2); /* get DMA status */ dma_stat = inb(dma_base+2); /* get DMA status */
outb(inb(dma_base)&~1, dma_base); /* stop DMA */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
ide_destroy_dmatable(drive); /* and free any DMA resources */ udma_destroy_table(ch); /* and free any DMA resources */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
default: default:
break; break;
...@@ -914,48 +915,48 @@ static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -914,48 +915,48 @@ static int cmd646_1_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
static int cmd680_busproc (ide_drive_t * drive, int state) static int cmd680_busproc(struct ata_device * drive, int state)
{ {
#if 0 #if 0
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
u8 addr_mask = (hwif->unit) ? 0xB0 : 0xA0; u8 addr_mask = (ch->unit) ? 0xB0 : 0xA0;
u32 stat_config = 0; u32 stat_config = 0;
pci_read_config_dword(hwif->pci_dev, addr_mask, &stat_config); pci_read_config_dword(ch->pci_dev, addr_mask, &stat_config);
if (!hwif) if (!ch)
return -EINVAL; return -EINVAL;
switch (state) { switch (state) {
case BUSSTATE_ON: case BUSSTATE_ON:
hwif->drives[0].failures = 0; ch->drives[0].failures = 0;
hwif->drives[1].failures = 0; ch->drives[1].failures = 0;
break; break;
case BUSSTATE_OFF: case BUSSTATE_OFF:
hwif->drives[0].failures = hwif->drives[0].max_failures + 1; ch->drives[0].failures = ch->drives[0].max_failures + 1;
hwif->drives[1].failures = hwif->drives[1].max_failures + 1; ch->drives[1].failures = ch->drives[1].max_failures + 1;
break; break;
case BUSSTATE_TRISTATE: case BUSSTATE_TRISTATE:
hwif->drives[0].failures = hwif->drives[0].max_failures + 1; ch->drives[0].failures = ch->drives[0].max_failures + 1;
hwif->drives[1].failures = hwif->drives[1].max_failures + 1; ch->drives[1].failures = ch->drives[1].max_failures + 1;
break; break;
default: default:
return 0; return 0;
} }
hwif->bus_state = state; ch->bus_state = state;
#endif #endif
return 0; return 0;
} }
static void cmd680_reset (ide_drive_t *drive) static void cmd680_reset(struct ata_device *drive)
{ {
#if 0 #if 0
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
u8 addr_mask = (hwif->unit) ? 0xB0 : 0xA0; u8 addr_mask = (ch->unit) ? 0xB0 : 0xA0;
byte reset = 0; u8 reset = 0;
pci_read_config_byte(hwif->pci_dev, addr_mask, &reset); pci_read_config_byte(ch->pci_dev, addr_mask, &reset);
pci_write_config_byte(hwif->pci_dev, addr_mask, reset|0x03); pci_write_config_byte(ch->pci_dev, addr_mask, reset|0x03);
#endif #endif
} }
......
...@@ -312,10 +312,10 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq) ...@@ -312,10 +312,10 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
* by HighPoint|Triones Technologies, Inc. * by HighPoint|Triones Technologies, Inc.
*/ */
int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq) int hpt34x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
unsigned long dma_base = hwif->dma_base; unsigned long dma_base = ch->dma_base;
unsigned int count, reading = 0; unsigned int count, reading = 0;
byte dma_stat; byte dma_stat;
...@@ -325,9 +325,9 @@ int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct requ ...@@ -325,9 +325,9 @@ int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct requ
case ide_dma_read: case ide_dma_read:
reading = 1 << 3; reading = 1 << 3;
case ide_dma_write: case ide_dma_write:
if (!(count = ide_build_dmatable(drive, func))) if (!(count = udma_new_table(ch, rq)))
return 1; /* try PIO instead of DMA */ return 1; /* try PIO instead of DMA */
outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
reading |= 0x01; reading |= 0x01;
outb(reading, dma_base); /* specify r/w */ outb(reading, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
...@@ -342,7 +342,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct requ ...@@ -342,7 +342,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct requ
outb(inb(dma_base)&~1, dma_base); /* stop DMA */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */ dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
ide_destroy_dmatable(drive); /* purge DMA mappings */ udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
default: default:
break; break;
......
...@@ -242,9 +242,9 @@ static int ide_build_sglist(struct ata_channel *hwif, struct request *rq) ...@@ -242,9 +242,9 @@ static int ide_build_sglist(struct ata_channel *hwif, struct request *rq)
} }
static int static int
icside_build_dmatable(ide_drive_t *drive, int reading) icside_udma_new_table(struct ata_channel *ch, struct request *rq)
{ {
return drive->channel->sg_nents = ide_build_sglist(drive->channel, HWGROUP(drive)->rq); return ch->sg_nents = ide_build_sglist(ch, rq);
} }
/* Teardown mappings after DMA has completed. */ /* Teardown mappings after DMA has completed. */
...@@ -332,7 +332,7 @@ static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request * ...@@ -332,7 +332,7 @@ static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request *
int i; int i;
byte stat, dma_stat; byte stat, dma_stat;
dma_stat = drive->channel->dmaproc(ide_dma_end, drive); dma_stat = drive->channel->udma(ide_dma_end, drive, rq);
stat = GET_STAT(); /* get drive status */ stat = GET_STAT(); /* get drive status */
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) { if (!dma_stat) {
...@@ -350,7 +350,7 @@ static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request * ...@@ -350,7 +350,7 @@ static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request *
static int static int
icside_dma_check(ide_drive_t *drive) icside_dma_check(struct ata_device *drive, struct request *rq)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -381,14 +381,7 @@ icside_dma_check(ide_drive_t *drive) ...@@ -381,14 +381,7 @@ icside_dma_check(ide_drive_t *drive)
out: out:
func = icside_config_if(drive, xfer_mode); func = icside_config_if(drive, xfer_mode);
return hwif->dmaproc(func, drive); return hwif->udma(func, drive, rq);
}
static int
icside_dma_verbose(ide_drive_t *drive)
{
printk(", DMA");
return 1;
} }
static int static int
...@@ -413,12 +406,12 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ...@@ -413,12 +406,12 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
return 0; return 0;
case ide_dma_check: case ide_dma_check:
return icside_dma_check(drive); return icside_dma_check(drive, rq);
case ide_dma_read: case ide_dma_read:
reading = 1; reading = 1;
case ide_dma_write: case ide_dma_write:
count = icside_build_dmatable(drive, reading); count = icside_udma_new_table(hwif, rq);
if (!count) if (!count)
return 1; return 1;
disable_dma(hwif->hw.dma); disable_dma(hwif->hw.dma);
...@@ -458,9 +451,6 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ...@@ -458,9 +451,6 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_test_irq: case ide_dma_test_irq:
return inb((unsigned long)hwif->hw.priv) & 1; return inb((unsigned long)hwif->hw.priv) & 1;
case ide_dma_verbose:
return icside_dma_verbose(drive);
case ide_dma_timeout: case ide_dma_timeout:
default: default:
printk("icside_dmaproc: unsupported function: %d\n", func); printk("icside_dmaproc: unsupported function: %d\n", func);
......
...@@ -2652,7 +2652,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) ...@@ -2652,7 +2652,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma) if (drive->using_dma)
(void) drive->channel->udma(ide_dma_verbose, drive, NULL); udma_print(drive);
#endif #endif
printk("\n"); printk("\n");
......
...@@ -89,7 +89,7 @@ static int lba_capacity_is_ok(struct hd_driveid *id) ...@@ -89,7 +89,7 @@ static int lba_capacity_is_ok(struct hd_driveid *id)
return 0; /* lba_capacity value may be bad */ return 0; /* lba_capacity value may be bad */
} }
static u8 get_command(ide_drive_t *drive, int cmd) static u8 get_command(struct ata_device *drive, int cmd)
{ {
int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
...@@ -345,7 +345,7 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -345,7 +345,7 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
return chs_do_request(drive, rq, block); return chs_do_request(drive, rq, block);
} }
static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) static int idedisk_open (struct inode *inode, struct file *filp, struct ata_device *drive)
{ {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if (drive->removable && drive->usage == 1) { if (drive->removable && drive->usage == 1) {
...@@ -370,7 +370,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr ...@@ -370,7 +370,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
return 0; return 0;
} }
static int idedisk_flushcache(ide_drive_t *drive) static int idedisk_flushcache(struct ata_device *drive)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -386,7 +386,7 @@ static int idedisk_flushcache(ide_drive_t *drive) ...@@ -386,7 +386,7 @@ static int idedisk_flushcache(ide_drive_t *drive)
return ide_raw_taskfile(drive, &args, NULL); return ide_raw_taskfile(drive, &args, NULL);
} }
static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) static void idedisk_release (struct inode *inode, struct file *filp, struct ata_device *drive)
{ {
if (drive->removable && !drive->usage) { if (drive->removable && !drive->usage) {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -408,7 +408,7 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t ...@@ -408,7 +408,7 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
static int idedisk_check_media_change (ide_drive_t *drive) static int idedisk_check_media_change(struct ata_device *drive)
{ {
/* if removable, always assume it was changed */ /* if removable, always assume it was changed */
return drive->removable; return drive->removable;
...@@ -474,7 +474,7 @@ static ide_startstop_t idedisk_special(struct ata_device *drive) ...@@ -474,7 +474,7 @@ static ide_startstop_t idedisk_special(struct ata_device *drive)
return IS_PDC4030_DRIVE ? ide_stopped : ide_started; return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
} }
static void idedisk_pre_reset (ide_drive_t *drive) static void idedisk_pre_reset(struct ata_device *drive)
{ {
int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
...@@ -490,7 +490,7 @@ static void idedisk_pre_reset (ide_drive_t *drive) ...@@ -490,7 +490,7 @@ static void idedisk_pre_reset (ide_drive_t *drive)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int smart_enable(ide_drive_t *drive) static int smart_enable(struct ata_device *drive)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -504,7 +504,7 @@ static int smart_enable(ide_drive_t *drive) ...@@ -504,7 +504,7 @@ static int smart_enable(ide_drive_t *drive)
return ide_raw_taskfile(drive, &args, NULL); return ide_raw_taskfile(drive, &args, NULL);
} }
static int get_smart_values(ide_drive_t *drive, u8 *buf) static int get_smart_values(struct ata_device *drive, u8 *buf)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -521,7 +521,7 @@ static int get_smart_values(ide_drive_t *drive, u8 *buf) ...@@ -521,7 +521,7 @@ static int get_smart_values(ide_drive_t *drive, u8 *buf)
return ide_raw_taskfile(drive, &args, buf); return ide_raw_taskfile(drive, &args, buf);
} }
static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) static int get_smart_thresholds(struct ata_device *drive, u8 *buf)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -541,7 +541,7 @@ static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) ...@@ -541,7 +541,7 @@ static int get_smart_thresholds(ide_drive_t *drive, u8 *buf)
static int proc_idedisk_read_cache static int proc_idedisk_read_cache
(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)
{ {
ide_drive_t *drive = (ide_drive_t *) data; struct ata_device *drive = (struct ata_device *) data;
char *out = page; char *out = page;
int len; int len;
...@@ -555,7 +555,7 @@ static int proc_idedisk_read_cache ...@@ -555,7 +555,7 @@ static int proc_idedisk_read_cache
static int proc_idedisk_read_smart_thresholds static int proc_idedisk_read_smart_thresholds
(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)
{ {
ide_drive_t *drive = (ide_drive_t *)data; struct ata_device *drive = (struct ata_device *)data;
int len = 0, i = 0; int len = 0, i = 0;
if (!get_smart_thresholds(drive, page)) { if (!get_smart_thresholds(drive, page)) {
...@@ -574,7 +574,7 @@ static int proc_idedisk_read_smart_thresholds ...@@ -574,7 +574,7 @@ static int proc_idedisk_read_smart_thresholds
static int proc_idedisk_read_smart_values static int proc_idedisk_read_smart_values
(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)
{ {
ide_drive_t *drive = (ide_drive_t *)data; struct ata_device *drive = (struct ata_device *)data;
int len = 0, i = 0; int len = 0, i = 0;
if (!get_smart_values(drive, page)) { if (!get_smart_values(drive, page)) {
...@@ -594,7 +594,7 @@ static int proc_idedisk_read_smart_values ...@@ -594,7 +594,7 @@ static int proc_idedisk_read_smart_values
static int proc_idedisk_read_tcq static int proc_idedisk_read_tcq
(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)
{ {
ide_drive_t *drive = (ide_drive_t *) data; struct ata_device *drive = (struct ata_device *) data;
char *out = page; char *out = page;
int len, cmds, i; int len, cmds, i;
unsigned long flags; unsigned long flags;
...@@ -658,7 +658,7 @@ static ide_proc_entry_t idedisk_proc[] = { ...@@ -658,7 +658,7 @@ static ide_proc_entry_t idedisk_proc[] = {
* This is tightly woven into the driver->special can not touch. * This is tightly woven into the driver->special can not touch.
* DON'T do it again until a total personality rewrite is committed. * DON'T do it again until a total personality rewrite is committed.
*/ */
static int set_multcount(ide_drive_t *drive, int arg) static int set_multcount(struct ata_device *drive, int arg)
{ {
struct request rq; struct request rq;
...@@ -670,12 +670,12 @@ static int set_multcount(ide_drive_t *drive, int arg) ...@@ -670,12 +670,12 @@ static int set_multcount(ide_drive_t *drive, int arg)
drive->mult_req = arg; drive->mult_req = arg;
drive->special_cmd |= ATA_SPECIAL_MMODE; drive->special_cmd |= ATA_SPECIAL_MMODE;
ide_do_drive_cmd (drive, &rq, ide_wait); ide_do_drive_cmd(drive, &rq, ide_wait);
return (drive->mult_count == arg) ? 0 : -EIO; return (drive->mult_count == arg) ? 0 : -EIO;
} }
static int set_nowerr(ide_drive_t *drive, int arg) static int set_nowerr(struct ata_device *drive, int arg)
{ {
if (ide_spin_wait_hwgroup(drive)) if (ide_spin_wait_hwgroup(drive))
return -EBUSY; return -EBUSY;
...@@ -686,7 +686,7 @@ static int set_nowerr(ide_drive_t *drive, int arg) ...@@ -686,7 +686,7 @@ static int set_nowerr(ide_drive_t *drive, int arg)
return 0; return 0;
} }
static int write_cache(ide_drive_t *drive, int arg) static int write_cache(struct ata_device *drive, int arg)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -704,7 +704,7 @@ static int write_cache(ide_drive_t *drive, int arg) ...@@ -704,7 +704,7 @@ static int write_cache(ide_drive_t *drive, int arg)
return 0; return 0;
} }
static int idedisk_standby(ide_drive_t *drive) static int idedisk_standby(struct ata_device *drive)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -715,7 +715,7 @@ static int idedisk_standby(ide_drive_t *drive) ...@@ -715,7 +715,7 @@ static int idedisk_standby(ide_drive_t *drive)
return ide_raw_taskfile(drive, &args, NULL); return ide_raw_taskfile(drive, &args, NULL);
} }
static int set_acoustic(ide_drive_t *drive, int arg) static int set_acoustic(struct ata_device *drive, int arg)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -732,7 +732,7 @@ static int set_acoustic(ide_drive_t *drive, int arg) ...@@ -732,7 +732,7 @@ static int set_acoustic(ide_drive_t *drive, int arg)
} }
#ifdef CONFIG_BLK_DEV_IDE_TCQ #ifdef CONFIG_BLK_DEV_IDE_TCQ
static int set_using_tcq(ide_drive_t *drive, int arg) static int set_using_tcq(struct ata_device *drive, int arg)
{ {
if (!drive->driver) if (!drive->driver)
return -EPERM; return -EPERM;
...@@ -750,14 +750,14 @@ static int set_using_tcq(ide_drive_t *drive, int arg) ...@@ -750,14 +750,14 @@ static int set_using_tcq(ide_drive_t *drive, int arg)
drive->queue_depth = drive->id->queue_depth + 1; drive->queue_depth = drive->id->queue_depth + 1;
} }
if (drive->channel->udma(arg ? ide_dma_queued_on : ide_dma_queued_off, drive, NULL)) if (udma_tcq_enable(drive, arg))
return -EIO; return -EIO;
return 0; return 0;
} }
#endif #endif
static int probe_lba_addressing (ide_drive_t *drive, int arg) static int probe_lba_addressing(struct ata_device *drive, int arg)
{ {
drive->addressing = 0; drive->addressing = 0;
...@@ -768,12 +768,12 @@ static int probe_lba_addressing (ide_drive_t *drive, int arg) ...@@ -768,12 +768,12 @@ static int probe_lba_addressing (ide_drive_t *drive, int arg)
return 0; return 0;
} }
static int set_lba_addressing (ide_drive_t *drive, int arg) static int set_lba_addressing(struct ata_device *drive, int arg)
{ {
return (probe_lba_addressing(drive, arg)); return (probe_lba_addressing(drive, arg));
} }
static void idedisk_add_settings(ide_drive_t *drive) static void idedisk_add_settings(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
...@@ -795,7 +795,7 @@ static void idedisk_add_settings(ide_drive_t *drive) ...@@ -795,7 +795,7 @@ static void idedisk_add_settings(ide_drive_t *drive)
static int idedisk_suspend(struct device *dev, u32 state, u32 level) static int idedisk_suspend(struct device *dev, u32 state, u32 level)
{ {
ide_drive_t *drive = dev->driver_data; struct ata_device *drive = dev->driver_data;
/* I hope that every freeze operations from the upper levels have /* I hope that every freeze operations from the upper levels have
* already been done... * already been done...
...@@ -822,7 +822,7 @@ static int idedisk_suspend(struct device *dev, u32 state, u32 level) ...@@ -822,7 +822,7 @@ static int idedisk_suspend(struct device *dev, u32 state, u32 level)
static int idedisk_resume(struct device *dev, u32 level) static int idedisk_resume(struct device *dev, u32 level)
{ {
ide_drive_t *drive = dev->driver_data; struct ata_device *drive = dev->driver_data;
if (level != RESUME_RESTORE_STATE) if (level != RESUME_RESTORE_STATE)
return 0; return 0;
...@@ -916,7 +916,7 @@ static u64 native_max_address_ext(struct ata_device *drive) ...@@ -916,7 +916,7 @@ static u64 native_max_address_ext(struct ata_device *drive)
* Sets maximum virtual LBA address of the drive. * Sets maximum virtual LBA address of the drive.
* Returns new maximum virtual LBA address (> 0) or 0 on failure. * Returns new maximum virtual LBA address (> 0) or 0 on failure.
*/ */
static sector_t set_max_address(ide_drive_t *drive, sector_t addr_req) static sector_t set_max_address(struct ata_device *drive, sector_t addr_req)
{ {
struct ata_taskfile args; struct ata_taskfile args;
sector_t addr_set = 0; sector_t addr_set = 0;
...@@ -945,7 +945,7 @@ static sector_t set_max_address(ide_drive_t *drive, sector_t addr_req) ...@@ -945,7 +945,7 @@ static sector_t set_max_address(ide_drive_t *drive, sector_t addr_req)
return addr_set; return addr_set;
} }
static u64 set_max_address_ext(ide_drive_t *drive, u64 addr_req) static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req)
{ {
struct ata_taskfile args; struct ata_taskfile args;
u64 addr_set = 0; u64 addr_set = 0;
...@@ -1177,7 +1177,7 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1177,7 +1177,7 @@ static void idedisk_setup(struct ata_device *drive)
drive->bios_cyl, drive->bios_head, drive->bios_sect); drive->bios_cyl, drive->bios_head, drive->bios_sect);
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma) if (drive->using_dma)
(void) drive->channel->udma(ide_dma_verbose, drive, NULL); udma_print(drive);
#endif #endif
printk("\n"); printk("\n");
...@@ -1213,7 +1213,7 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1213,7 +1213,7 @@ static void idedisk_setup(struct ata_device *drive)
probe_lba_addressing(drive, 1); probe_lba_addressing(drive, 1);
} }
static int idedisk_cleanup(ide_drive_t *drive) static int idedisk_cleanup(struct ata_device *drive)
{ {
if (!drive) if (!drive)
return 0; return 0;
...@@ -1250,7 +1250,7 @@ MODULE_DESCRIPTION("ATA DISK Driver"); ...@@ -1250,7 +1250,7 @@ MODULE_DESCRIPTION("ATA DISK Driver");
static void __exit idedisk_exit (void) static void __exit idedisk_exit (void)
{ {
ide_drive_t *drive; struct ata_device *drive;
int failed = 0; int failed = 0;
while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", &idedisk_driver, failed)) != NULL) { while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", &idedisk_driver, failed)) != NULL) {
...@@ -1267,9 +1267,9 @@ static void __exit idedisk_exit (void) ...@@ -1267,9 +1267,9 @@ static void __exit idedisk_exit (void)
} }
} }
int idedisk_init (void) int idedisk_init(void)
{ {
ide_drive_t *drive; struct ata_device *drive;
int failed = 0; int failed = 0;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
......
This diff is collapsed.
...@@ -44,29 +44,38 @@ ...@@ -44,29 +44,38 @@
*/ */
char *ide_xfer_verbose (byte xfer_rate) char *ide_xfer_verbose (byte xfer_rate)
{ {
switch(xfer_rate) { static struct ide_xfer_par {
case XFER_UDMA_7: return("UDMA 7"); byte rate;
case XFER_UDMA_6: return("UDMA 6"); char *name;
case XFER_UDMA_5: return("UDMA 5"); } xfer_verbose[] = {
case XFER_UDMA_4: return("UDMA 4"); { XFER_UDMA_7, "UDMA 7" },
case XFER_UDMA_3: return("UDMA 3"); { XFER_UDMA_6, "UDMA 6" },
case XFER_UDMA_2: return("UDMA 2"); { XFER_UDMA_5, "UDMA 5" },
case XFER_UDMA_1: return("UDMA 1"); { XFER_UDMA_4, "UDMA 4" },
case XFER_UDMA_0: return("UDMA 0"); { XFER_UDMA_3, "UDMA 3" },
case XFER_MW_DMA_2: return("MW DMA 2"); { XFER_UDMA_2, "UDMA 2" },
case XFER_MW_DMA_1: return("MW DMA 1"); { XFER_UDMA_1, "UDMA 1" },
case XFER_MW_DMA_0: return("MW DMA 0"); { XFER_UDMA_0, "UDMA 0" },
case XFER_SW_DMA_2: return("SW DMA 2"); { XFER_MW_DMA_2, "MW DMA 2" },
case XFER_SW_DMA_1: return("SW DMA 1"); { XFER_MW_DMA_1, "MW DMA 1" },
case XFER_SW_DMA_0: return("SW DMA 0"); { XFER_MW_DMA_0, "MW DMA 0" },
case XFER_PIO_4: return("PIO 4"); { XFER_SW_DMA_2, "SW DMA 2" },
case XFER_PIO_3: return("PIO 3"); { XFER_SW_DMA_1, "SW DMA 1" },
case XFER_PIO_2: return("PIO 2"); { XFER_SW_DMA_0, "SW DMA 0" },
case XFER_PIO_1: return("PIO 1"); { XFER_PIO_4, "PIO 4" },
case XFER_PIO_0: return("PIO 0"); { XFER_PIO_3, "PIO 3" },
case XFER_PIO_SLOW: return("PIO SLOW"); { XFER_PIO_2, "PIO 2" },
default: return("XFER ERROR"); { XFER_PIO_1, "PIO 1" },
} { XFER_PIO_0, "PIO 0" },
{ XFER_PIO_SLOW, "PIO SLOW" },
};
int i = 0;
for (; i < ARRAY_SIZE(xfer_verbose); i++)
if (xfer_verbose[i].rate == xfer_rate)
return xfer_verbose[i].name;
return "XFER ERROR";
} }
byte ide_auto_reduce_xfer (ide_drive_t *drive) byte ide_auto_reduce_xfer (ide_drive_t *drive)
......
...@@ -1164,9 +1164,9 @@ pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, in ...@@ -1164,9 +1164,9 @@ pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, in
/* Teardown mappings after DMA has completed. */ /* Teardown mappings after DMA has completed. */
static void static void
pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix) pmac_ide_destroy_dmatable(struct ata_channel *ch, int ix)
{ {
struct pci_dev *dev = drive->channel->pci_dev; struct pci_dev *dev = ch->pci_dev;
struct scatterlist *sg = pmac_ide[ix].sg_table; struct scatterlist *sg = pmac_ide[ix].sg_table;
int nents = pmac_ide[ix].sg_nents; int nents = pmac_ide[ix].sg_nents;
...@@ -1367,10 +1367,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1367,10 +1367,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
break; break;
case ide_dma_read: case ide_dma_read:
case ide_dma_write: case ide_dma_write:
/* this almost certainly isn't needed since we don't
appear to have a rwproc */
if (drive->channel->rwproc)
drive->channel->rwproc(drive, func);
reading = (func == ide_dma_read); 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;
...@@ -1404,7 +1400,7 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1404,7 +1400,7 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
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); pmac_ide_destroy_dmatable(drive->channel, 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: /* returns 1 if dma irq issued, 0 otherwise */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
...@@ -1453,8 +1449,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1453,8 +1449,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
case ide_dma_bad_drive: case ide_dma_bad_drive:
case ide_dma_good_drive: case ide_dma_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive)); return check_drive_lists(drive, (func == ide_dma_good_drive));
case ide_dma_verbose:
return report_drive_dmaing(drive);
case ide_dma_retune: case ide_dma_retune:
case ide_dma_lostirq: case ide_dma_lostirq:
case ide_dma_timeout: case ide_dma_timeout:
......
...@@ -448,7 +448,7 @@ static inline void probe_for_drive(struct ata_device *drive) ...@@ -448,7 +448,7 @@ static inline void probe_for_drive(struct ata_device *drive)
*/ */
static void channel_probe(struct ata_channel *ch) static void channel_probe(struct ata_channel *ch)
{ {
unsigned int unit; unsigned int i;
unsigned long flags; unsigned long flags;
int error; int error;
...@@ -463,8 +463,8 @@ static void channel_probe(struct ata_channel *ch) ...@@ -463,8 +463,8 @@ static void channel_probe(struct ata_channel *ch)
/* /*
* Check for the presence of a channel by probing for drives on it. * Check for the presence of a channel by probing for drives on it.
*/ */
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (i = 0; i < MAX_DRIVES; ++i) {
struct ata_device *drive = &ch->drives[unit]; struct ata_device *drive = &ch->drives[i];
probe_for_drive(drive); probe_for_drive(drive);
...@@ -483,23 +483,8 @@ static void channel_probe(struct ata_channel *ch) ...@@ -483,23 +483,8 @@ static void channel_probe(struct ata_channel *ch)
error += !request_region(ch->io_ports[IDE_DATA_OFFSET], 8, ch->name); error += !request_region(ch->io_ports[IDE_DATA_OFFSET], 8, ch->name);
ch->straight8 = 1; ch->straight8 = 1;
} else { } else {
if (ch->io_ports[IDE_DATA_OFFSET]) for (i = 0; i < 8; i++)
error += !request_region(ch->io_ports[IDE_DATA_OFFSET], 1, ch->name); error += !request_region(ch->io_ports[i], 1, ch->name);
if (ch->io_ports[IDE_ERROR_OFFSET])
error += !request_region(ch->io_ports[IDE_ERROR_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_NSECTOR_OFFSET])
error += !request_region(ch->io_ports[IDE_NSECTOR_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_SECTOR_OFFSET])
error += !request_region(ch->io_ports[IDE_SECTOR_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_LCYL_OFFSET])
error += !request_region(ch->io_ports[IDE_LCYL_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_HCYL_OFFSET])
error += !request_region(ch->io_ports[IDE_HCYL_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_SELECT_OFFSET])
error += !request_region(ch->io_ports[IDE_SELECT_OFFSET], 1, ch->name);
if (ch->io_ports[IDE_STATUS_OFFSET])
error += !request_region(ch->io_ports[IDE_STATUS_OFFSET], 1, ch->name);
} }
if (ch->io_ports[IDE_CONTROL_OFFSET]) if (ch->io_ports[IDE_CONTROL_OFFSET])
error += !request_region(ch->io_ports[IDE_CONTROL_OFFSET], 1, ch->name); error += !request_region(ch->io_ports[IDE_CONTROL_OFFSET], 1, ch->name);
...@@ -561,8 +546,8 @@ static void channel_probe(struct ata_channel *ch) ...@@ -561,8 +546,8 @@ static void channel_probe(struct ata_channel *ch)
/* /*
* Now setup the PIO transfer modes of the drives on this channel. * Now setup the PIO transfer modes of the drives on this channel.
*/ */
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (i = 0; i < MAX_DRIVES; ++i) {
struct ata_device *drive = &ch->drives[unit]; struct ata_device *drive = &ch->drives[i];
if (drive->present && (drive->autotune == 1)) { if (drive->present && (drive->autotune == 1)) {
if (drive->channel->tuneproc) if (drive->channel->tuneproc)
...@@ -819,6 +804,16 @@ static void channel_init(struct ata_channel *ch) ...@@ -819,6 +804,16 @@ static void channel_init(struct ata_channel *ch)
goto err_kmalloc_gd_part; goto err_kmalloc_gd_part;
memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct)); memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct));
gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
if (!gd->de_arr)
goto err_kmalloc_gd_de_arr;
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
if (!gd->flags)
goto err_kmalloc_gd_flags;
memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit)
ch->drives[unit].part = &gd->part[unit << PARTN_BITS]; ch->drives[unit].part = &gd->part[unit << PARTN_BITS];
......
...@@ -130,12 +130,12 @@ static void ata_write_slow(struct ata_device *drive, void *buffer, unsigned int ...@@ -130,12 +130,12 @@ static void ata_write_slow(struct ata_device *drive, void *buffer, unsigned int
} }
#endif #endif
static void ata_read_16(ide_drive_t *drive, void *buffer, unsigned int wcount) static void ata_read_16(struct ata_device *drive, void *buffer, unsigned int wcount)
{ {
insw(IDE_DATA_REG, buffer, wcount<<1); insw(IDE_DATA_REG, buffer, wcount<<1);
} }
static void ata_write_16(ide_drive_t *drive, void *buffer, unsigned int wcount) static void ata_write_16(struct ata_device *drive, void *buffer, unsigned int wcount)
{ {
outsw(IDE_DATA_REG, buffer, wcount<<1); outsw(IDE_DATA_REG, buffer, wcount<<1);
} }
...@@ -143,7 +143,7 @@ static void ata_write_16(ide_drive_t *drive, void *buffer, unsigned int wcount) ...@@ -143,7 +143,7 @@ static void ata_write_16(ide_drive_t *drive, void *buffer, unsigned int wcount)
/* /*
* This is used for most PIO data transfers *from* the device. * This is used for most PIO data transfers *from* the device.
*/ */
void ata_read(ide_drive_t *drive, void *buffer, unsigned int wcount) void ata_read(struct ata_device *drive, void *buffer, unsigned int wcount)
{ {
int io_32bit; int io_32bit;
...@@ -178,7 +178,7 @@ void ata_read(ide_drive_t *drive, void *buffer, unsigned int wcount) ...@@ -178,7 +178,7 @@ void ata_read(ide_drive_t *drive, void *buffer, unsigned int wcount)
/* /*
* This is used for most PIO data transfers *to* the device interface. * This is used for most PIO data transfers *to* the device interface.
*/ */
void ata_write(ide_drive_t *drive, void *buffer, unsigned int wcount) void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount)
{ {
int io_32bit; int io_32bit;
...@@ -213,7 +213,7 @@ void ata_write(ide_drive_t *drive, void *buffer, unsigned int wcount) ...@@ -213,7 +213,7 @@ void ata_write(ide_drive_t *drive, void *buffer, unsigned int wcount)
* so if an odd bytecount is specified, be sure that there's at least one * so if an odd bytecount is specified, be sure that there's at least one
* extra byte allocated for the buffer. * extra byte allocated for the buffer.
*/ */
void atapi_read(ide_drive_t *drive, void *buffer, unsigned int bytecount) void atapi_read(struct ata_device *drive, void *buffer, unsigned int bytecount)
{ {
if (drive->channel->atapi_read) { if (drive->channel->atapi_read) {
drive->channel->atapi_read(drive, buffer, bytecount); drive->channel->atapi_read(drive, buffer, bytecount);
...@@ -233,7 +233,7 @@ void atapi_read(ide_drive_t *drive, void *buffer, unsigned int bytecount) ...@@ -233,7 +233,7 @@ void atapi_read(ide_drive_t *drive, void *buffer, unsigned int bytecount)
insw(IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); insw(IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
} }
void atapi_write(ide_drive_t *drive, void *buffer, unsigned int bytecount) void atapi_write(struct ata_device *drive, void *buffer, unsigned int bytecount)
{ {
if (drive->channel->atapi_write) { if (drive->channel->atapi_write) {
drive->channel->atapi_write(drive, buffer, bytecount); drive->channel->atapi_write(drive, buffer, bytecount);
...@@ -256,7 +256,7 @@ void atapi_write(ide_drive_t *drive, void *buffer, unsigned int bytecount) ...@@ -256,7 +256,7 @@ void atapi_write(ide_drive_t *drive, void *buffer, unsigned int bytecount)
/* /*
* Needed for PCI irq sharing * Needed for PCI irq sharing
*/ */
int drive_is_ready(ide_drive_t *drive) int drive_is_ready(struct ata_device *drive)
{ {
byte stat = 0; byte stat = 0;
if (drive->waiting_for_dma) if (drive->waiting_for_dma)
...@@ -290,7 +290,7 @@ int drive_is_ready(ide_drive_t *drive) ...@@ -290,7 +290,7 @@ int drive_is_ready(ide_drive_t *drive)
* Stuff the first sector(s) by implicitly calling the handler driectly * Stuff the first sector(s) by implicitly calling the handler driectly
* therafter. * therafter.
*/ */
void ata_poll_drive_ready(ide_drive_t *drive) void ata_poll_drive_ready(struct ata_device *drive)
{ {
int i; int i;
...@@ -399,7 +399,7 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -399,7 +399,7 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
return ide_started; return ide_started;
} }
ide_startstop_t ata_taskfile(ide_drive_t *drive, ide_startstop_t ata_taskfile(struct ata_device *drive,
struct ata_taskfile *args, struct request *rq) struct ata_taskfile *args, struct request *rq)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
...@@ -456,40 +456,39 @@ ide_startstop_t ata_taskfile(ide_drive_t *drive, ...@@ -456,40 +456,39 @@ ide_startstop_t ata_taskfile(ide_drive_t *drive,
if (args->prehandler != NULL) if (args->prehandler != NULL)
return args->prehandler(drive, rq); return args->prehandler(drive, rq);
} else { } else {
/*
* FIXME: this is a gross hack, need to unify tcq dma proc and
* regular dma proc -- basically split stuff that needs to act
* on a request from things like ide_dma_check etc.
*/
ide_dma_action_t dma_act; ide_dma_action_t dma_act;
int tcq = 0;
if (!drive->using_dma) if (!drive->using_dma)
return ide_started; return ide_started;
/* for dma commands we don't set the handler */ /* for dma commands we don't set the handler */
if (args->taskfile.command == WIN_WRITEDMA || args->taskfile.command == WIN_WRITEDMA_EXT) if (args->taskfile.command == WIN_WRITEDMA
|| args->taskfile.command == WIN_WRITEDMA_EXT)
dma_act = ide_dma_write; dma_act = ide_dma_write;
else if (args->taskfile.command == WIN_READDMA || args->taskfile.command == WIN_READDMA_EXT) else if (args->taskfile.command == WIN_READDMA
|| args->taskfile.command == WIN_READDMA_EXT)
dma_act = ide_dma_read; dma_act = ide_dma_read;
else if (args->taskfile.command == WIN_WRITEDMA_QUEUED || args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT) { #ifdef CONFIG_BLK_DEV_IDE_TCQ
tcq = 1; else if (args->taskfile.command == WIN_WRITEDMA_QUEUED
dma_act = ide_dma_write_queued; || args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT
} else if (args->taskfile.command == WIN_READDMA_QUEUED || args->taskfile.command == WIN_READDMA_QUEUED_EXT) { || args->taskfile.command == WIN_READDMA_QUEUED
tcq = 1; || args->taskfile.command == WIN_READDMA_QUEUED_EXT)
dma_act = ide_dma_read_queued; return udma_tcq_taskfile(drive, rq);
} else { #endif
else {
printk("ata_taskfile: unknown command %x\n", args->taskfile.command); printk("ata_taskfile: unknown command %x\n", args->taskfile.command);
return ide_stopped; return ide_stopped;
} }
/*
* FIXME: this is a gross hack, need to unify tcq dma proc and
* regular dma proc -- basically split stuff that needs to act
* on a request from things like ide_dma_check etc.
*/
if (tcq)
return drive->channel->udma(dma_act, drive, rq);
else {
if (drive->channel->udma(dma_act, drive, rq)) if (drive->channel->udma(dma_act, drive, rq))
return ide_stopped; return ide_stopped;
} }
}
return ide_started; return ide_started;
} }
...@@ -900,7 +899,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args) ...@@ -900,7 +899,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
} }
} }
int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *args, byte *buf) int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args, byte *buf)
{ {
struct request rq; struct request rq;
...@@ -926,7 +925,7 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *args, byte *buf) ...@@ -926,7 +925,7 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *args, byte *buf)
* interface. * interface.
*/ */
int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg)
{ {
int err = 0; int err = 0;
u8 vals[4]; u8 vals[4];
......
This diff is collapsed.
...@@ -93,7 +93,7 @@ static int ns87415_dmaproc(ide_dma_action_t func, struct ata_device *drive, stru ...@@ -93,7 +93,7 @@ static int ns87415_dmaproc(ide_dma_action_t func, struct ata_device *drive, stru
dma_stat = inb(hwif->dma_base+2); dma_stat = inb(hwif->dma_base+2);
outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */
outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */
ide_destroy_dmatable(drive); /* and free any DMA resources */ udma_destroy_table(hwif); /* and free any DMA resources */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_write: case ide_dma_write:
case ide_dma_read: case ide_dma_read:
......
...@@ -215,6 +215,8 @@ static int wait_altstat(struct ata_device *drive, u8 *stat, u8 busy_mask) ...@@ -215,6 +215,8 @@ static int wait_altstat(struct ata_device *drive, u8 *stat, u8 busy_mask)
return 0; return 0;
} }
static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq);
/* /*
* issue SERVICE command to drive -- drive must have been selected first, * issue SERVICE command to drive -- drive must have been selected first,
* and it must have reported a need for service (status has SERVICE_STAT set) * and it must have reported a need for service (status has SERVICE_STAT set)
...@@ -296,7 +298,7 @@ static ide_startstop_t service(struct ata_device *drive) ...@@ -296,7 +298,7 @@ static ide_startstop_t service(struct ata_device *drive)
* interrupt to indicate end of transfer, release is not allowed * interrupt to indicate end of transfer, release is not allowed
*/ */
TCQ_PRINTK("%s: starting command %x\n", __FUNCTION__, stat); TCQ_PRINTK("%s: starting command %x\n", __FUNCTION__, stat);
return drive->channel->udma(ide_dma_queued_start, drive, rq); return udma_tcq_start(drive, rq);
} }
static ide_startstop_t check_service(struct ata_device *drive) static ide_startstop_t check_service(struct ata_device *drive)
...@@ -483,47 +485,6 @@ static int configure_tcq(struct ata_device *drive) ...@@ -483,47 +485,6 @@ static int configure_tcq(struct ata_device *drive)
return 0; return 0;
} }
/*
* for now assume that command list is always as big as we need and don't
* attempt to shrink it on tcq disable
*/
static int enable_queued(struct ata_device *drive, int on)
{
int depth = drive->using_tcq ? drive->queue_depth : 0;
/*
* disable or adjust queue depth
*/
if (!on) {
if (drive->using_tcq)
printk("%s: TCQ disabled\n", drive->name);
drive->using_tcq = 0;
return 0;
}
if (configure_tcq(drive)) {
drive->using_tcq = 0;
return 1;
}
/*
* enable block tagging
*/
if (!blk_queue_tagged(&drive->queue))
blk_queue_init_tags(&drive->queue, IDE_MAX_TAG);
/*
* check auto-poll support
*/
check_autopoll(drive);
if (depth != drive->queue_depth)
printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
drive->using_tcq = 1;
return 0;
}
static int tcq_wait_dataphase(struct ata_device *drive) static int tcq_wait_dataphase(struct ata_device *drive)
{ {
u8 stat; u8 stat;
...@@ -547,40 +508,43 @@ static int tcq_wait_dataphase(struct ata_device *drive) ...@@ -547,40 +508,43 @@ static int tcq_wait_dataphase(struct ata_device *drive)
return 0; return 0;
} }
ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) /****************************************************************************
{ * UDMA transfer handling functions.
struct ata_channel *hwif = drive->channel; */
unsigned int enable_tcq = 1;
u8 stat;
u8 feat;
switch (func) { /*
/* * Invoked from a SERVICE interrupt, command etc already known. Just need to
* invoked from a SERVICE interrupt, command etc already known. * start the dma engine for this tag.
* just need to start the dma engine for this tag
*/ */
case ide_dma_queued_start: static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq)
TCQ_PRINTK("ide_dma: setting up queued %d\n", rq->tag); {
if (!test_bit(IDE_BUSY, &HWGROUP(drive)->flags)) struct ata_channel *ch = drive->channel;
TCQ_PRINTK("%s: setting up queued %d\n", __FUNCTION__, rq->tag);
if (!test_bit(IDE_BUSY, &ch->hwgroup->flags))
printk("queued_rw: IDE_BUSY not set\n"); printk("queued_rw: IDE_BUSY not set\n");
if (tcq_wait_dataphase(drive)) if (tcq_wait_dataphase(drive))
return ide_stopped; return ide_stopped;
if (ide_start_dma(func, drive)) if (ata_start_dma(drive, rq))
return ide_stopped; return ide_stopped;
set_irq(drive, ide_dmaq_intr); set_irq(drive, ide_dmaq_intr);
if (!hwif->udma(ide_dma_begin, drive, rq)) if (!ch->udma(ide_dma_begin, drive, rq))
return ide_started; return ide_started;
return ide_stopped; return ide_stopped;
}
/* /*
* start a queued command from scratch * Start a queued command from scratch.
*/ */
case ide_dma_read_queued: ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq)
case ide_dma_write_queued: { {
u8 stat;
u8 feat;
struct ata_taskfile *args = rq->special; struct ata_taskfile *args = rq->special;
TCQ_PRINTK("%s: start tag %d\n", drive->name, rq->tag); TCQ_PRINTK("%s: start tag %d\n", drive->name, rq->tag);
...@@ -625,18 +589,47 @@ ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t func, struct ata_device *drive, ...@@ -625,18 +589,47 @@ ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t func, struct ata_device *drive,
TCQ_PRINTK("IMMED in queued_start\n"); TCQ_PRINTK("IMMED in queued_start\n");
drive->immed_comp++; drive->immed_comp++;
return hwif->udma(ide_dma_queued_start, drive, rq);
return udma_tcq_start(drive, rq);
}
/*
* For now assume that command list is always as big as we need and don't
* attempt to shrink it on tcq disable.
*/
int udma_tcq_enable(struct ata_device *drive, int on)
{
int depth = drive->using_tcq ? drive->queue_depth : 0;
/*
* disable or adjust queue depth
*/
if (!on) {
if (drive->using_tcq)
printk("%s: TCQ disabled\n", drive->name);
drive->using_tcq = 0;
return 0;
} }
case ide_dma_queued_off: if (configure_tcq(drive)) {
enable_tcq = 0; drive->using_tcq = 0;
case ide_dma_queued_on:
if (enable_tcq && !drive->using_dma)
return 1; return 1;
return enable_queued(drive, enable_tcq);
default:
break;
} }
return 1; /*
* enable block tagging
*/
if (!blk_queue_tagged(&drive->queue))
blk_queue_init_tags(&drive->queue, IDE_MAX_TAG);
/*
* check auto-poll support
*/
check_autopoll(drive);
if (depth != drive->queue_depth)
printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
drive->using_tcq = 1;
return 0;
} }
...@@ -175,7 +175,7 @@ static void trm290_selectproc (ide_drive_t *drive) ...@@ -175,7 +175,7 @@ static void trm290_selectproc (ide_drive_t *drive)
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
unsigned int count, reading = 2, writing = 0; unsigned int count, reading = 2, writing = 0;
switch (func) { switch (func) {
...@@ -186,12 +186,12 @@ static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, stru ...@@ -186,12 +186,12 @@ static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, stru
break; /* always use PIO for writes */ break; /* always use PIO for writes */
#endif #endif
case ide_dma_read: case ide_dma_read:
if (!(count = ide_build_dmatable(drive, func))) if (!(count = udma_new_table(ch, rq)))
break; /* try PIO instead of DMA */ break; /* try PIO instead of DMA */
trm290_prepare_drive(drive, 1); /* select DMA xfer */ trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(hwif->dmatable_dma|reading|writing, hwif->dma_base); outl(ch->dmatable_dma|reading|writing, ch->dma_base);
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
...@@ -201,10 +201,10 @@ static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, stru ...@@ -201,10 +201,10 @@ static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, stru
return 0; return 0;
case ide_dma_end: case ide_dma_end:
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
ide_destroy_dmatable(drive); /* purge DMA mappings */ udma_destroy_table(ch); /* purge DMA mappings */
return (inw(hwif->dma_base+2) != 0x00ff); return (inw(ch->dma_base + 2) != 0x00ff);
case ide_dma_test_irq: case ide_dma_test_irq:
return (inw(hwif->dma_base+2) == 0x00ff); return (inw(ch->dma_base + 2) == 0x00ff);
default: default:
return ide_dmaproc(func, drive, rq); return ide_dmaproc(func, drive, rq);
} }
......
...@@ -373,26 +373,18 @@ struct ata_device { ...@@ -373,26 +373,18 @@ struct ata_device {
int max_depth; int max_depth;
} ide_drive_t; } ide_drive_t;
/* typedef enum {
* This initiates/aborts DMA read/write operations on a drive. ide_dma_read, ide_dma_write,
* ide_dma_begin, ide_dma_end,
* The caller is assumed to have selected the drive and programmed the drive's ide_dma_check,
* sector address using CHS or LBA. All that remains is to prepare for DMA ide_dma_on, ide_dma_off,
* and then issue the actual read/write DMA/PIO command to the drive. ide_dma_off_quietly,
* ide_dma_test_irq,
* Returns 0 if all went well. ide_dma_bad_drive,
* Returns 1 if DMA read/write could not be started, in which case the caller ide_dma_good_drive,
* should either try again later, or revert to PIO for the current request. ide_dma_retune,
*/ ide_dma_lostirq,
typedef enum { ide_dma_read, ide_dma_write, ide_dma_begin, ide_dma_timeout
ide_dma_end, ide_dma_check, ide_dma_on,
ide_dma_off, ide_dma_off_quietly, ide_dma_test_irq,
ide_dma_bad_drive, ide_dma_good_drive,
ide_dma_verbose, ide_dma_retune,
ide_dma_lostirq, ide_dma_timeout,
ide_dma_read_queued, ide_dma_write_queued,
ide_dma_queued_start, ide_dma_queued_on,
ide_dma_queued_off,
} ide_dma_action_t; } ide_dma_action_t;
enum { enum {
...@@ -435,9 +427,6 @@ struct ata_channel { ...@@ -435,9 +427,6 @@ struct ata_channel {
/* special host masking for drive selection */ /* special host masking for drive selection */
void (*maskproc) (struct ata_device *, int); void (*maskproc) (struct ata_device *, int);
/* adjust timing based upon rq->cmd direction */
void (*rwproc) (struct ata_device *, ide_dma_action_t);
/* check host's drive quirk list */ /* check host's drive quirk list */
int (*quirkproc) (struct ata_device *); int (*quirkproc) (struct ata_device *);
...@@ -471,6 +460,7 @@ struct ata_channel { ...@@ -471,6 +460,7 @@ struct ata_channel {
unsigned autodma : 1; /* automatically try to enable DMA at boot */ unsigned autodma : 1; /* automatically try to enable DMA at boot */
unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */ unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */
unsigned highmem : 1; /* can do full 32-bit dma */ unsigned highmem : 1; /* can do full 32-bit dma */
unsigned straight8 : 1; /* Alan's straight 8 check */
unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */
unsigned no_unmask : 1; /* disallow setting unmask bit */ unsigned no_unmask : 1; /* disallow setting unmask bit */
unsigned auto_poll : 1; /* supports nop auto-poll */ unsigned auto_poll : 1; /* supports nop auto-poll */
...@@ -481,8 +471,8 @@ struct ata_channel { ...@@ -481,8 +471,8 @@ struct ata_channel {
#if (DISK_RECOVERY_TIME > 0) #if (DISK_RECOVERY_TIME > 0)
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 */ /* driver soft-power interface */
int (*busproc)(struct ata_device *, int); /* driver soft-power interface */ int (*busproc)(struct ata_device *, int);
byte bus_state; /* power state of the IDE bus */ byte bus_state; /* power state of the IDE bus */
}; };
...@@ -561,7 +551,7 @@ typedef struct hwgroup_s { ...@@ -561,7 +551,7 @@ typedef struct hwgroup_s {
#define SETTING_WRITE (1 << 1) #define SETTING_WRITE (1 << 1)
#define SETTING_RW (SETTING_READ | SETTING_WRITE) #define SETTING_RW (SETTING_READ | SETTING_WRITE)
typedef int (ide_procset_t)(ide_drive_t *, int); typedef int (ide_procset_t)(struct ata_device *, int);
typedef struct ide_settings_s { typedef struct ide_settings_s {
char *name; char *name;
int rw; int rw;
...@@ -578,11 +568,11 @@ typedef struct ide_settings_s { ...@@ -578,11 +568,11 @@ typedef struct ide_settings_s {
struct ide_settings_s *next; struct ide_settings_s *next;
} ide_settings_t; } ide_settings_t;
void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set); extern void ide_add_setting(struct ata_device *, const char *, int, int, int, int, int, int, int, int, void *, ide_procset_t *);
void ide_remove_setting(ide_drive_t *drive, char *name); extern void ide_remove_setting(struct ata_device *, char *);
int ide_read_setting(ide_drive_t *t, ide_settings_t *setting); extern int ide_read_setting(struct ata_device *, ide_settings_t *);
int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val); extern int ide_write_setting(struct ata_device *, ide_settings_t *, int);
void ide_add_generic_settings(ide_drive_t *drive); extern void ide_add_generic_settings(struct ata_device *);
/* /*
* /proc/ide interface * /proc/ide interface
...@@ -695,19 +685,19 @@ extern void ide_set_handler(struct ata_device *drive, ata_handler_t handler, ...@@ -695,19 +685,19 @@ extern void ide_set_handler(struct ata_device *drive, ata_handler_t handler,
/* /*
* Error reporting, in human readable form (luxurious, but a memory hog). * Error reporting, in human readable form (luxurious, but a memory hog).
*/ */
byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat); extern byte ide_dump_status(struct ata_device *, const char *, byte);
/* /*
* ide_error() takes action based on the error returned by the controller. * ide_error() takes action based on the error returned by the controller.
* The caller should return immediately after invoking this. * The caller should return immediately after invoking this.
*/ */
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); extern ide_startstop_t ide_error(struct ata_device *, const char *, byte);
/* /*
* Issue a simple drive command * Issue a simple drive command
* The drive must be selected beforehand. * The drive must be selected beforehand.
*/ */
void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ata_handler_t handler); void ide_cmd(struct ata_device *, byte, byte, ata_handler_t);
/* /*
* ide_fixstring() cleans up and (optionally) byte-swaps a text string, * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
...@@ -725,9 +715,9 @@ void ide_fixstring(byte *s, const int bytecount, const int byteswap); ...@@ -725,9 +715,9 @@ void ide_fixstring(byte *s, const int bytecount, const int byteswap);
* caller should return the updated value of "startstop" in this case. * caller should return the updated value of "startstop" in this case.
* "startstop" is unchanged when the function returns 0; * "startstop" is unchanged when the function returns 0;
*/ */
int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout); extern int ide_wait_stat(ide_startstop_t *, struct ata_device *, byte, byte, unsigned long);
int ide_wait_noerr(ide_drive_t *drive, byte good, byte bad, unsigned long timeout); extern int ide_wait_noerr(struct ata_device *, byte, byte, unsigned long);
/* /*
* This routine is called from the partition-table code in genhd.c * This routine is called from the partition-table code in genhd.c
...@@ -736,15 +726,15 @@ int ide_wait_noerr(ide_drive_t *drive, byte good, byte bad, unsigned long timeou ...@@ -736,15 +726,15 @@ int ide_wait_noerr(ide_drive_t *drive, byte good, byte bad, unsigned long timeou
int ide_xlate_1024(kdev_t, int, int, const char *); int ide_xlate_1024(kdev_t, int, int, const char *);
/* /*
* Convert kdev_t structure into ide_drive_t * one. * Convert kdev_t structure into struct ata_device * one.
*/ */
ide_drive_t *get_info_ptr(kdev_t i_rdev); struct ata_device *get_info_ptr(kdev_t i_rdev);
/* /*
* Re-Start an operation for an IDE interface. * Re-Start an operation for an IDE interface.
* The caller should return immediately after invoking this. * The caller should return immediately after invoking this.
*/ */
ide_startstop_t restart_request(ide_drive_t *); ide_startstop_t restart_request(struct ata_device *);
/* /*
* This function is intended to be used prior to invoking ide_do_drive_cmd(). * This function is intended to be used prior to invoking ide_do_drive_cmd().
...@@ -766,12 +756,12 @@ typedef enum { ...@@ -766,12 +756,12 @@ typedef enum {
*/ */
#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) #define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
extern int ide_do_drive_cmd(ide_drive_t *drive, struct request *rq, ide_action_t action); extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
/* /*
* Clean up after success/failure of an explicit drive cmd. * Clean up after success/failure of an explicit drive cmd.
*/ */
void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err); extern void ide_end_drive_cmd(struct ata_device *, byte, byte);
struct ata_taskfile { struct ata_taskfile {
struct hd_drive_task_hdr taskfile; struct hd_drive_task_hdr taskfile;
...@@ -808,31 +798,20 @@ extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg); ...@@ -808,31 +798,20 @@ extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg);
void ide_delay_50ms(void); void ide_delay_50ms(void);
byte ide_auto_reduce_xfer (ide_drive_t *drive); extern byte ide_auto_reduce_xfer(struct ata_device *);
int ide_driveid_update (ide_drive_t *drive); extern int ide_driveid_update(struct ata_device *);
int ide_ata66_check (ide_drive_t *drive, struct ata_taskfile *args); extern int ide_ata66_check(struct ata_device *, struct ata_taskfile *);
int ide_config_drive_speed (ide_drive_t *drive, byte speed); extern int ide_config_drive_speed(struct ata_device *, byte);
byte eighty_ninty_three (ide_drive_t *drive); extern byte eighty_ninty_three(struct ata_device *);
int set_transfer (ide_drive_t *drive, struct ata_taskfile *args); extern int set_transfer(struct ata_device *, struct ata_taskfile *);
extern int system_bus_speed; extern int system_bus_speed;
/*
* idedisk_input_data() is a wrapper around ide_input_data() which copes
* with byte-swapping the input data if required.
*/
extern void idedisk_input_data(ide_drive_t *drive, void *buffer, unsigned int wcount);
/* /*
* ide_stall_queue() can be used by a drive to give excess bandwidth back * ide_stall_queue() can be used by a drive to give excess bandwidth back
* to the hwgroup by sleeping for timeout jiffies. * to the hwgroup by sleeping for timeout jiffies.
*/ */
void ide_stall_queue (ide_drive_t *drive, unsigned long timeout); void ide_stall_queue(struct ata_device *, unsigned long);
/*
* ide_get_queue() returns the queue which corresponds to a given device.
*/
request_queue_t *ide_get_queue(kdev_t dev);
/* /*
* CompactFlash cards and their brethern pretend to be removable hard disks, * CompactFlash cards and their brethern pretend to be removable hard disks,
...@@ -841,9 +820,9 @@ request_queue_t *ide_get_queue(kdev_t dev); ...@@ -841,9 +820,9 @@ request_queue_t *ide_get_queue(kdev_t dev);
* config bits. * config bits.
*/ */
extern int drive_is_flashcard(ide_drive_t *drive); extern int drive_is_flashcard(struct ata_device *);
int ide_spin_wait_hwgroup (ide_drive_t *drive); int ide_spin_wait_hwgroup(struct ata_device *);
void ide_timer_expiry (unsigned long data); void ide_timer_expiry (unsigned long data);
extern void ata_irq_request(int irq, void *data, struct pt_regs *regs); extern void ata_irq_request(int irq, void *data, struct pt_regs *regs);
void do_ide_request (request_queue_t * q); void do_ide_request (request_queue_t * q);
...@@ -889,15 +868,21 @@ extern int ide_unregister_subdriver(struct ata_device *drive); ...@@ -889,15 +868,21 @@ extern int ide_unregister_subdriver(struct ata_device *drive);
void __init ide_scan_pcibus(int scan_direction); void __init ide_scan_pcibus(int scan_direction);
#endif #endif
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
extern int ide_build_dmatable(struct ata_device *, ide_dma_action_t);
extern void ide_destroy_dmatable(struct ata_device *); extern int udma_new_table(struct ata_channel *, struct request *);
extern void udma_destroy_table(struct ata_channel *);
extern void udma_print(struct ata_device *);
extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *);
extern int udma_tcq_enable(struct ata_device *, int);
extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *); extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *);
extern int check_drive_lists(struct ata_device *, int good_bad); extern int check_drive_lists(struct ata_device *, int good_bad);
extern int ide_dmaproc(ide_dma_action_t func, struct ata_device *, struct request *); extern int ide_dmaproc(ide_dma_action_t func, struct ata_device *, struct request *);
extern ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t, struct ata_device *, struct request *); extern ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t, struct ata_device *, struct request *);
extern void ide_release_dma(struct ata_channel *); extern void ide_release_dma(struct ata_channel *);
extern void ide_setup_dma(struct ata_channel *, unsigned long, unsigned int) __init; extern void ide_setup_dma(struct ata_channel *, unsigned long, unsigned int) __init;
extern int ide_start_dma(ide_dma_action_t, struct ata_device *); extern int ata_start_dma(struct ata_device *, struct request *rq);
#endif #endif
extern spinlock_t ide_lock; extern spinlock_t ide_lock;
......
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