This is a multi-part message in MIME format. ------=_NextPart_000_0041_01C4C57D.A0B5F640 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Updated IDE driver for Linux 2.6.9. Signed-off-by: Mikael Starvik ------=_NextPart_000_0041_01C4C57D.A0B5F640 Content-Type: application/octet-stream; name="cris269_4.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="cris269_4.patch" ../linux/arch/cris/arch-v10/drivers/ide.c = lx25/arch/cris/arch-v10/drivers/ide.c Signed-off-by: Andrew Morton --- /dev/null | 0 25-akpm/arch/cris/arch-v10/drivers/ide.c | 179 +++++++++++++++++++++---------- 2 files changed, 124 insertions(+), 55 deletions(-) diff -puN arch/cris/arch-v10/drivers/ide.c~cris-architecture-update-ide-driver arch/cris/arch-v10/drivers/ide.c --- 25/arch/cris/arch-v10/drivers/ide.c~cris-architecture-update-ide-driver Mon Nov 8 14:19:28 2004 +++ 25-akpm/arch/cris/arch-v10/drivers/ide.c Mon Nov 8 14:19:28 2004 @@ -1,4 +1,4 @@ -/* $Id: ide.c,v 1.1 2004/01/22 08:22:58 starvik Exp $ +/* $Id: ide.c,v 1.4 2004/10/12 07:55:48 starvik Exp $ * * Etrax specific IDE functions, like init and PIO-mode setting etc. * Almost the entire ide.c is used for the rest of the Etrax ATA driver. @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -46,18 +45,13 @@ #define IDE_REGISTER_TIMEOUT 300 -#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET -/* address where the memory-mapped IDE reset bit lives, if used */ -static volatile unsigned long *reset_addr; -#endif - static int e100_read_command = 0; #define LOWDB(x) #define D(x) void -etrax100_ide_outw(unsigned short data, ide_ioreg_t reg) { +etrax100_ide_outw(unsigned short data, unsigned long reg) { int timeleft; LOWDB(printk("ow: data 0x%x, reg 0x%x\n", data, reg)); @@ -90,7 +84,7 @@ etrax100_ide_outw(unsigned short data, i } void -etrax100_ide_outb(unsigned char data, ide_ioreg_t reg) +etrax100_ide_outb(unsigned char data, unsigned long reg) { etrax100_ide_outw(data, reg); } @@ -102,7 +96,7 @@ etrax100_ide_outbsync(ide_drive_t *drive } unsigned short -etrax100_ide_inw(ide_ioreg_t reg) { +etrax100_ide_inw(unsigned long reg) { int status; int timeleft; @@ -150,7 +144,7 @@ etrax100_ide_inw(ide_ioreg_t reg) { } unsigned char -etrax100_ide_inb(ide_ioreg_t reg) +etrax100_ide_inb(unsigned long reg) { return (unsigned char)etrax100_ide_inw(reg); } @@ -208,8 +202,10 @@ etrax100_ide_inb(ide_ioreg_t reg) #define ATA_PIO0_HOLD 4 static int e100_dma_check (ide_drive_t *drive); -static void e100_dma_start(ide_drive_t *drive); +static int e100_dma_begin (ide_drive_t *drive); static int e100_dma_end (ide_drive_t *drive); +static int e100_dma_read (ide_drive_t *drive); +static int e100_dma_write (ide_drive_t *drive); static void e100_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void e100_ide_output_data (ide_drive_t *drive, void *, unsigned int); static void e100_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); @@ -280,40 +276,6 @@ static void tune_e100_ide(ide_drive_t *d } } -static int e100_dma_setup(ide_drive_t *drive) -{ - struct request *rq = drive->hwif->hwgroup->rq; - - if (rq_data_dir(rq)) { - e100_read_command = 0; - - RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_TX_DMA_NBR); - } else { - e100_read_command = 1; - - RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_RX_DMA_NBR); - } - - /* set up the Etrax DMA descriptors */ - if (e100_ide_build_dmatable(drive)) { - ide_map_sg(drive, rq); - return 1; - } - - return 0; -} - -static void e100_dma_exec_cmd(ide_drive_t *drive, u8 command) -{ - /* set the irq handler which will finish the request when DMA is done */ - ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); - - /* issue cmd to drive */ - etrax100_ide_outb(command, IDE_COMMAND_REG); -} - void __init init_e100_ide (void) { @@ -335,9 +297,9 @@ init_e100_ide (void) hwif->atapi_output_bytes = &e100_atapi_output_bytes; hwif->ide_dma_check = &e100_dma_check; hwif->ide_dma_end = &e100_dma_end; - hwif->dma_setup = &e100_dma_setup; - hwif->dma_exec_cmd = &e100_dma_exec_cmd; - hwif->dma_start = &e100_dma_start; + hwif->ide_dma_write = &e100_dma_write; + hwif->ide_dma_read = &e100_dma_read; + hwif->ide_dma_begin = &e100_dma_begin; hwif->OUTB = &etrax100_ide_outb; hwif->OUTW = &etrax100_ide_outw; hwif->OUTBSYNC = &etrax100_ide_outbsync; @@ -457,7 +419,7 @@ static etrax_dma_descr mydescr; static void e100_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) { - ide_ioreg_t data_reg = IDE_DATA_REG; + unsigned long data_reg = IDE_DATA_REG; D(printk("atapi_input_bytes, dreg 0x%x, buffer 0x%x, count %d\n", data_reg, buffer, bytecount)); @@ -536,7 +498,7 @@ e100_atapi_input_bytes (ide_drive_t *dri static void e100_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) { - ide_ioreg_t data_reg = IDE_DATA_REG; + unsigned long data_reg = IDE_DATA_REG; D(printk("atapi_output_bytes, dreg 0x%x, buffer 0x%x, count %d\n", data_reg, buffer, bytecount)); @@ -656,9 +618,20 @@ static int e100_ide_build_dmatable (ide_ ata_tot_size = 0; - ide_map_sg(drive, rq); + if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { + u8 *virt_addr = rq->buffer; + int sector_count = rq->nr_sectors; + memset(&sg[0], 0, sizeof(*sg)); + sg[0].page = virt_to_page(virt_addr); + sg[0].offset = offset_in_page(virt_addr); + sg[0].length = sector_count * SECTOR_SIZE; + hwif->sg_nents = i = 1; + } + else + { + hwif->sg_nents = i = blk_rq_map_sg(drive->queue, rq, hwif->sg_table); + } - i = hwif->sg_nents; while(i) { /* @@ -795,6 +768,10 @@ static ide_startstop_t etrax_dma_intr (i * sector address using CHS or LBA. All that remains is to prepare for DMA * and then issue the actual read/write DMA/PIO command to the drive. * + * For ATAPI devices, we just prepare for DMA and return. The caller should + * then issue the packet command to the drive and call us again with + * ide_dma_begin afterwards. + * * Returns 0 if all went well. * Returns 1 if DMA read/write could not be started, in which case * the caller should revert to PIO for the current request. @@ -811,9 +788,35 @@ static int e100_dma_end(ide_drive_t *dri return 0; } -static void e100_dma_start(ide_drive_t *drive) +static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) { - if (e100_read_command) { + if(reading) { + + RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_RX_DMA_NBR); + + /* set up the Etrax DMA descriptors */ + + if(e100_ide_build_dmatable (drive)) + return 1; + + if(!atapi) { + /* set the irq handler which will finish the request when DMA is done */ + + ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + + /* issue cmd to drive */ + if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + etrax100_ide_outb(WIN_READDMA_EXT, IDE_COMMAND_REG); + } else { + etrax100_ide_outb(WIN_READDMA, IDE_COMMAND_REG); + } + } + /* begin DMA */ /* need to do this before RX DMA due to a chip bug @@ -846,6 +849,32 @@ static void e100_dma_start(ide_drive_t * } else { /* writing */ + + RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_TX_DMA_NBR); + + /* set up the Etrax DMA descriptors */ + + if(e100_ide_build_dmatable (drive)) + return 1; + + if(!atapi) { + /* set the irq handler which will finish the request when DMA is done */ + + ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + + /* issue cmd to drive */ + if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + etrax100_ide_outb(WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + etrax100_ide_outb(WIN_WRITEDMA, IDE_COMMAND_REG); + } + } + /* begin DMA */ *R_DMA_CH2_FIRST = virt_to_phys(ata_descrs); @@ -868,4 +897,44 @@ static void e100_dma_start(ide_drive_t * D(printk("dma write of %d bytes.\n", ata_tot_size)); } + return 0; +} + +static int e100_dma_write(ide_drive_t *drive) +{ + e100_read_command = 0; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 0); +} + +static int e100_dma_read(ide_drive_t *drive) +{ + e100_read_command = 1; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 1); +} + +static int e100_dma_begin(ide_drive_t *drive) +{ + /* begin DMA, used by ATAPI devices which want to issue the + * appropriate IDE command themselves. + * + * they have already called ide_dma_read/write to set the + * static reading flag, now they call ide_dma_begin to do + * the real stuff. we tell our code below not to issue + * any IDE commands itself and jump into it. + */ + return e100_start_dma(drive, 1, e100_read_command); } diff -L linux/arch/cris/arch-v10/drivers/ide.c -puN /dev/null /dev/null _