linux-old/drivers/ide/ide-taskfile.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/ide/ide-taskfile.c     Version 0.38    March 05, 2003
   3 *
   4 *  Copyright (C) 2000-2002     Michael Cornwell <cornwell@acm.org>
   5 *  Copyright (C) 2000-2002     Andre Hedrick <andre@linux-ide.org>
   6 *  Copyright (C) 2001-2002     Klaus Smolin
   7 *                                      IBM Storage Technology Division
   8 *
   9 *  The big the bad and the ugly.
  10 *
  11 *  Problems to be fixed because of BH interface or the lack therefore.
  12 *
  13 *  Fill me in stupid !!!
  14 *
  15 *  HOST:
  16 *      General refers to the Controller and Driver "pair".
  17 *  DATA HANDLER:
  18 *      Under the context of Linux it generally refers to an interrupt handler.
  19 *      However, it correctly describes the 'HOST'
  20 *  DATA BLOCK:
  21 *      The amount of data needed to be transfered as predefined in the
  22 *      setup of the device.
  23 *  STORAGE ATOMIC:
  24 *      The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as
  25 *      small as a single sector or as large as the entire command block
  26 *      request.
  27 */
  28
  29#include <linux/config.h>
  30#define __NO_VERSION__
  31#include <linux/module.h>
  32#include <linux/types.h>
  33#include <linux/string.h>
  34#include <linux/kernel.h>
  35#include <linux/timer.h>
  36#include <linux/mm.h>
  37#include <linux/interrupt.h>
  38#include <linux/major.h>
  39#include <linux/errno.h>
  40#include <linux/genhd.h>
  41#include <linux/blkpg.h>
  42#include <linux/slab.h>
  43#include <linux/pci.h>
  44#include <linux/delay.h>
  45#include <linux/hdreg.h>
  46#include <linux/ide.h>
  47
  48#include <asm/byteorder.h>
  49#include <asm/irq.h>
  50#include <asm/uaccess.h>
  51#include <asm/io.h>
  52#include <asm/bitops.h>
  53
  54#define DEBUG_TASKFILE  0       /* unset when fixed */
  55
  56#if DEBUG_TASKFILE
  57#define DTF(x...) printk(x)
  58#else
  59#define DTF(x...)
  60#endif
  61
  62/*
  63 *
  64 */
  65#define task_rq_offset(rq) \
  66        (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE)
  67
  68/*
  69 * for now, taskfile requests are special :/
  70 *
  71 * However, upon the creation of the atapi version of packet_command
  72 * data-phase ISR plus it own diagnostics and extensions for direct access
  73 * (ioctl,read,write,rip,stream -- atapi), the kmap/kunmap for PIO will
  74 * come localized.
  75 */
  76inline char *task_map_rq (struct request *rq, unsigned long *flags)
  77{
  78        if (rq->bh)
  79                return ide_map_buffer(rq, flags);
  80        return rq->buffer + task_rq_offset(rq);
  81}
  82
  83inline void task_unmap_rq (struct request *rq, char *buf, unsigned long *flags)
  84{
  85        if (rq->bh)
  86                ide_unmap_buffer(buf, flags);
  87}
  88
  89inline u32 task_read_24 (ide_drive_t *drive)
  90{
  91        return  (HWIF(drive)->INB(IDE_HCYL_REG)<<16) |
  92                (HWIF(drive)->INB(IDE_LCYL_REG)<<8) |
  93                 HWIF(drive)->INB(IDE_SECTOR_REG);
  94}
  95
  96EXPORT_SYMBOL(task_read_24);
  97
  98static void ata_bswap_data (void *buffer, int wcount)
  99{
 100        u16 *p = buffer;
 101
 102        while (wcount--) {
 103                *p = *p << 8 | *p >> 8; p++;
 104                *p = *p << 8 | *p >> 8; p++;
 105        }
 106}
 107
 108
 109void taskfile_input_data (ide_drive_t *drive, void *buffer, u32 wcount)
 110{
 111        HWIF(drive)->ata_input_data(drive, buffer, wcount);
 112        if (drive->bswap)
 113                ata_bswap_data(buffer, wcount);
 114}
 115
 116EXPORT_SYMBOL(taskfile_input_data);
 117
 118void taskfile_output_data (ide_drive_t *drive, void *buffer, u32 wcount)
 119{
 120        if (drive->bswap) {
 121                ata_bswap_data(buffer, wcount);
 122                HWIF(drive)->ata_output_data(drive, buffer, wcount);
 123                ata_bswap_data(buffer, wcount);
 124        } else {
 125                HWIF(drive)->ata_output_data(drive, buffer, wcount);
 126        }
 127}
 128
 129EXPORT_SYMBOL(taskfile_output_data);
 130
 131int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
 132{
 133        ide_task_t args;
 134        memset(&args, 0, sizeof(ide_task_t));
 135        args.tfRegister[IDE_NSECTOR_OFFSET]     = 0x01;
 136        if (drive->media == ide_disk)
 137                args.tfRegister[IDE_COMMAND_OFFSET]     = WIN_IDENTIFY;
 138        else
 139                args.tfRegister[IDE_COMMAND_OFFSET]     = WIN_PIDENTIFY;
 140        args.command_type                       = ide_cmd_type_parser(&args);
 141        return ide_raw_taskfile(drive, &args, buf);
 142}
 143
 144EXPORT_SYMBOL(taskfile_lib_get_identify);
 145
 146#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
 147void debug_taskfile (ide_drive_t *drive, ide_task_t *args)
 148{
 149        printk(KERN_INFO "%s: ", drive->name);
 150//      printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]);
 151        printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]);
 152        printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]);
 153        printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]);
 154        printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]);
 155        printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]);
 156        printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]);
 157        printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]);
 158        printk(KERN_INFO "%s: ", drive->name);
 159//      printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]);
 160        printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]);
 161        printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]);
 162        printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]);
 163        printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]);
 164        printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]);
 165        printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]);
 166        printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]);
 167}
 168#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
 169
 170ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 171{
 172        ide_hwif_t *hwif        = HWIF(drive);
 173        task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
 174        hob_struct_t *hobfile   = (hob_struct_t *) task->hobRegister;
 175        u8 HIHI                 = (drive->addressing == 1) ? 0xE0 : 0xEF;
 176
 177#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
 178        void debug_taskfile(drive, task);
 179#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
 180
 181        /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
 182        if (IDE_CONTROL_REG) {
 183                /* clear nIEN */
 184                hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 185        }
 186        SELECT_MASK(drive, 0);
 187
 188        if (drive->addressing == 1) {
 189                hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
 190                hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
 191                hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
 192                hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
 193                hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
 194        }
 195
 196        hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
 197        hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
 198        hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
 199        hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
 200        hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
 201
 202        hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
 203        if (task->handler != NULL) {
 204                ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
 205                if (task->prehandler != NULL)
 206                        return task->prehandler(drive, task->rq);
 207                return ide_started;
 208        }
 209        /* for dma commands we down set the handler */
 210#if 0
 211        if (blk_fs_request(task->rq) && drive->using_dma) {
 212                if (rq_data_dir(task->rq) == READ) {
 213                        if (hwif->ide_dma_read(drive))
 214                                return ide_stopped;
 215                } else {
 216                        if (hwif->ide_dma_write(drive))
 217                                return ide_stopped;
 218                }
 219        } else {
 220                if (!drive->using_dma && (task->handler == NULL))
 221                        return ide_stopped;
 222
 223                switch(taskfile->command) {
 224                        case WIN_WRITEDMA_ONCE:
 225                        case WIN_WRITEDMA:
 226                        case WIN_WRITEDMA_EXT:
 227                                hwif->ide_dma_write(drive);
 228                                break;
 229                        case WIN_READDMA_ONCE:
 230                        case WIN_READDMA:
 231                        case WIN_READDMA_EXT:
 232                        case WIN_IDENTIFY_DMA:
 233                                hwif->ide_dma_read(drive);
 234                                break;
 235                        default:
 236                                if (task->handler == NULL)
 237                                        return ide_stopped;
 238                }
 239        }
 240        return ide_started;
 241#else
 242        switch(taskfile->command) {
 243                case WIN_WRITEDMA_ONCE:
 244                case WIN_WRITEDMA:
 245                case WIN_WRITEDMA_EXT:
 246                        if (drive->using_dma && !(hwif->ide_dma_write(drive)))
 247                                return ide_started;
 248                case WIN_READDMA_ONCE:
 249                case WIN_READDMA:
 250                case WIN_READDMA_EXT:
 251                case WIN_IDENTIFY_DMA:
 252                        if (drive->using_dma && !(hwif->ide_dma_read(drive)))
 253                                return ide_started;
 254                default:
 255                        break;
 256        }
 257        return ide_stopped;
 258#endif
 259}
 260
 261EXPORT_SYMBOL(do_rw_taskfile);
 262
 263/*
 264 * Error reporting, in human readable form (luxurious, but a memory hog).
 265 */
 266u8 taskfile_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 267{
 268        ide_hwif_t *hwif = HWIF(drive);
 269        unsigned long flags;
 270        u8 err = 0;
 271
 272        local_irq_set(flags);
 273        printk("%s: %s: status=0x%02x", drive->name, msg, stat);
 274#if FANCY_STATUS_DUMPS
 275        printk(" { ");
 276        if (stat & BUSY_STAT) {
 277                printk("Busy ");
 278        } else {
 279                if (stat & READY_STAT)  printk("DriveReady ");
 280                if (stat & WRERR_STAT)  printk("DeviceFault ");
 281                if (stat & SEEK_STAT)   printk("SeekComplete ");
 282                if (stat & DRQ_STAT)    printk("DataRequest ");
 283                if (stat & ECC_STAT)    printk("CorrectedError ");
 284                if (stat & INDEX_STAT)  printk("Index ");
 285                if (stat & ERR_STAT)    printk("Error ");
 286        }
 287        printk("}");
 288#endif  /* FANCY_STATUS_DUMPS */
 289        printk("\n");
 290        if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
 291                err = hwif->INB(IDE_ERROR_REG);
 292                printk("%s: %s: error=0x%02x", drive->name, msg, err);
 293#if FANCY_STATUS_DUMPS
 294                if (drive->media == ide_disk)
 295                        goto media_out;
 296
 297                printk(" { ");
 298                if (err & ABRT_ERR)     printk("DriveStatusError ");
 299                if (err & ICRC_ERR)     printk("Bad%s", (err & ABRT_ERR) ? "CRC " : "Sector ");
 300                if (err & ECC_ERR)      printk("UncorrectableError ");
 301                if (err & ID_ERR)       printk("SectorIdNotFound ");
 302                if (err & TRK0_ERR)     printk("TrackZeroNotFound ");
 303                if (err & MARK_ERR)     printk("AddrMarkNotFound ");
 304                printk("}");
 305                if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
 306                    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
 307                        if (drive->addressing == 1) {
 308                                u64 sectors = 0;
 309                                u32 high = 0;
 310                                u32 low = task_read_24(drive);
 311                                hwif->OUTB(0x80, IDE_CONTROL_REG);
 312                                high = task_read_24(drive);
 313                                sectors = ((u64)high << 24) | low;
 314                                printk(", LBAsect=%lld", sectors);
 315                        } else {
 316                                u8 cur  = hwif->INB(IDE_SELECT_REG);
 317                                u8 low  = hwif->INB(IDE_LCYL_REG);
 318                                u8 high = hwif->INB(IDE_HCYL_REG);
 319                                u8 sect = hwif->INB(IDE_SECTOR_REG);
 320                                /* using LBA? */
 321                                if (cur & 0x40) {
 322                                        printk(", LBAsect=%d", (u32)
 323                                                ((cur&0xf)<<24)|(high<<16)|
 324                                                (low<<8)|sect);
 325                                } else {
 326                                        printk(", CHS=%d/%d/%d",
 327                                                ((high<<8) + low),
 328                                                (cur & 0xf), sect);
 329                                }
 330                        }
 331                        if (HWGROUP(drive)->rq)
 332                                printk(", sector=%lu",
 333                                        HWGROUP(drive)->rq->sector);
 334                }
 335media_out:
 336#endif  /* FANCY_STATUS_DUMPS */
 337                printk("\n");
 338        }
 339        local_irq_restore(flags);
 340        return err;
 341}
 342
 343EXPORT_SYMBOL(taskfile_dump_status);
 344
 345/*
 346 * Clean up after success/failure of an explicit taskfile operation.
 347 */
 348void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err)
 349{
 350        ide_hwif_t *hwif = HWIF(drive);
 351        unsigned long flags;
 352        struct request *rq;
 353        ide_task_t *args;
 354        task_ioreg_t command;
 355
 356        spin_lock_irqsave(&io_request_lock, flags);
 357        rq = HWGROUP(drive)->rq;
 358        spin_unlock_irqrestore(&io_request_lock, flags);
 359        args = (ide_task_t *) rq->special;
 360
 361        command = args->tfRegister[IDE_COMMAND_OFFSET];
 362
 363        if (rq->errors == 0)
 364                rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
 365
 366        if (args->tf_in_flags.b.data) {
 367                u16 data = hwif->INW(IDE_DATA_REG);
 368                args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
 369                args->hobRegister[IDE_DATA_OFFSET_HOB]  = (data >> 8) & 0xFF;
 370        }
 371        args->tfRegister[IDE_ERROR_OFFSET]   = err;
 372        args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
 373        args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
 374        args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
 375        args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
 376        args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
 377        args->tfRegister[IDE_STATUS_OFFSET]  = stat;
 378        if ((drive->id->command_set_2 & 0x0400) &&
 379            (drive->id->cfs_enable_2 & 0x0400) &&
 380            (drive->addressing == 1)) {
 381                hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
 382                args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
 383                args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
 384                args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = hwif->INB(IDE_SECTOR_REG);
 385                args->hobRegister[IDE_LCYL_OFFSET_HOB]    = hwif->INB(IDE_LCYL_REG);
 386                args->hobRegister[IDE_HCYL_OFFSET_HOB]    = hwif->INB(IDE_HCYL_REG);
 387        }
 388
 389#if 0
 390/*      taskfile_settings_update(drive, args, command); */
 391
 392        if (args->posthandler != NULL)
 393                args->posthandler(drive, args);
 394#endif
 395
 396        spin_lock_irqsave(&io_request_lock, flags);
 397        blkdev_dequeue_request(rq);
 398        HWGROUP(drive)->rq = NULL;
 399        end_that_request_last(rq);
 400        spin_unlock_irqrestore(&io_request_lock, flags);
 401}
 402
 403EXPORT_SYMBOL(ide_end_taskfile);
 404
 405/*
 406 * try_to_flush_leftover_data() is invoked in response to a drive
 407 * unexpectedly having its DRQ_STAT bit set.  As an alternative to
 408 * resetting the drive, this routine tries to clear the condition
 409 * by read a sector's worth of data from the drive.  Of course,
 410 * this may not help if the drive is *waiting* for data from *us*.
 411 */
 412void task_try_to_flush_leftover_data (ide_drive_t *drive)
 413{
 414        int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
 415
 416        if (drive->media != ide_disk)
 417                return;
 418        while (i > 0) {
 419                u32 buffer[16];
 420                unsigned int wcount = (i > 16) ? 16 : i;
 421                i -= wcount;
 422                taskfile_input_data(drive, buffer, wcount);
 423        }
 424}
 425
 426EXPORT_SYMBOL(task_try_to_flush_leftover_data);
 427
 428/*
 429 * taskfile_error() takes action based on the error returned by the drive.
 430 */
 431ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, u8 stat)
 432{
 433        ide_hwif_t *hwif;
 434        struct request *rq;
 435        u8 err;
 436
 437        err = taskfile_dump_status(drive, msg, stat);
 438        if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
 439                return ide_stopped;
 440
 441        hwif = HWIF(drive);
 442        /* retry only "normal" I/O: */
 443        if (rq->cmd == IDE_DRIVE_TASKFILE) {
 444                rq->errors = 1;
 445                ide_end_taskfile(drive, stat, err);
 446                return ide_stopped;
 447        }
 448        if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
 449                /* other bits are useless when BUSY */
 450                rq->errors |= ERROR_RESET;
 451        } else {
 452                if (drive->media != ide_disk)
 453                        goto media_out;
 454                if (stat & ERR_STAT) {
 455                        /* err has different meaning on cdrom and tape */
 456                        if (err == ABRT_ERR) {
 457                                if (drive->select.b.lba &&
 458                                    (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY))
 459                                        /* some newer drives don't
 460                                         * support WIN_SPECIFY
 461                                         */
 462                                        return ide_stopped;
 463                        } else if ((err & BAD_CRC) == BAD_CRC) {
 464                                /* UDMA crc error -- just retry the operation */
 465                                drive->crc_count++;
 466                        } else if (err & (BBD_ERR | ECC_ERR)) {
 467                                /* retries won't help these */
 468                                rq->errors = ERROR_MAX;
 469                        } else if (err & TRK0_ERR) {
 470                                /* help it find track zero */
 471                                rq->errors |= ERROR_RECAL;
 472                        }
 473                }
 474media_out:
 475                if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE)
 476                        task_try_to_flush_leftover_data(drive);
 477        }
 478        if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
 479                /* force an abort */
 480                hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
 481        }
 482        if (rq->errors >= ERROR_MAX) {
 483                DRIVER(drive)->end_request(drive, 0);
 484        } else {
 485                if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
 486                        ++rq->errors;
 487                        return ide_do_reset(drive);
 488                }
 489                if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
 490                        drive->special.b.recalibrate = 1;
 491                ++rq->errors;
 492        }
 493        return ide_stopped;
 494}
 495
 496EXPORT_SYMBOL(taskfile_error);
 497
 498/*
 499 * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
 500 */
 501ide_startstop_t set_multmode_intr (ide_drive_t *drive)
 502{
 503        ide_hwif_t *hwif = HWIF(drive);
 504        u8 stat;
 505
 506        if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
 507                drive->mult_count = drive->mult_req;
 508        } else {
 509                drive->mult_req = drive->mult_count = 0;
 510                drive->special.b.recalibrate = 1;
 511                (void) ide_dump_status(drive, "set_multmode", stat);
 512        }
 513        return ide_stopped;
 514}
 515
 516EXPORT_SYMBOL(set_multmode_intr);
 517
 518/*
 519 * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
 520 */
 521ide_startstop_t set_geometry_intr (ide_drive_t *drive)
 522{
 523        ide_hwif_t *hwif = HWIF(drive);
 524        int retries = 5;
 525        u8 stat;
 526
 527        while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
 528                udelay(10);
 529
 530        if (OK_STAT(stat, READY_STAT, BAD_STAT))
 531                return ide_stopped;
 532
 533        if (stat & (ERR_STAT|DRQ_STAT))
 534                return DRIVER(drive)->error(drive, "set_geometry_intr", stat);
 535
 536        if (HWGROUP(drive)->handler != NULL)
 537                BUG();
 538        ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
 539        return ide_started;
 540}
 541
 542EXPORT_SYMBOL(set_geometry_intr);
 543
 544/*
 545 * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
 546 */
 547ide_startstop_t recal_intr (ide_drive_t *drive)
 548{
 549        ide_hwif_t *hwif = HWIF(drive);
 550        u8 stat;
 551
 552        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT))
 553                return DRIVER(drive)->error(drive, "recal_intr", stat);
 554        return ide_stopped;
 555}
 556
 557EXPORT_SYMBOL(recal_intr);
 558
 559/*
 560 * Handler for commands without a data phase
 561 */
 562ide_startstop_t task_no_data_intr (ide_drive_t *drive)
 563{
 564        ide_task_t *args        = HWGROUP(drive)->rq->special;
 565        ide_hwif_t *hwif        = HWIF(drive);
 566        u8 stat;
 567
 568        local_irq_enable();
 569        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
 570                DTF("%s: command opcode 0x%02x\n", drive->name,
 571                        args->tfRegister[IDE_COMMAND_OFFSET]);
 572                return DRIVER(drive)->error(drive, "task_no_data_intr", stat);
 573                /* calls ide_end_drive_cmd */
 574        }
 575        if (args)
 576                ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
 577
 578        return ide_stopped;
 579}
 580
 581EXPORT_SYMBOL(task_no_data_intr);
 582
 583/*
 584 * Handler for command with PIO data-in phase, READ
 585 */
 586/*
 587 * FIXME before 2.4 enable ...
 588 *      DATA integrity issue upon error. <andre@linux-ide.org>
 589 */
 590ide_startstop_t task_in_intr (ide_drive_t *drive)
 591{
 592        struct request *rq      = HWGROUP(drive)->rq;
 593        ide_hwif_t *hwif        = HWIF(drive);
 594        char *pBuf              = NULL;
 595        u8 stat;
 596        unsigned long flags;
 597
 598        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
 599                if (stat & (ERR_STAT|DRQ_STAT)) {
 600#if 0
 601                        DTF("%s: attempting to recover last " \
 602                                "sector counter status=0x%02x\n",
 603                                drive->name, stat);
 604                        /*
 605                         * Expect a BUG BOMB if we attempt to rewind the
 606                         * offset in the BH aka PAGE in the current BLOCK
 607                         * segment.  This is different than the HOST segment.
 608                         */
 609#endif
 610                        if (!rq->bh)
 611                                rq->current_nr_sectors++;
 612                        return DRIVER(drive)->error(drive, "task_in_intr", stat);
 613                }
 614                if (!(stat & BUSY_STAT)) {
 615                        DTF("task_in_intr to Soon wait for next interrupt\n");
 616                        if (HWGROUP(drive)->handler == NULL)
 617                                ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
 618                        return ide_started;  
 619                }
 620        }
 621#if 0
 622
 623        /*
 624         * Holding point for a brain dump of a thought :-/
 625         */
 626
 627        if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
 628                DTF("%s: READ attempting to recover last " \
 629                        "sector counter status=0x%02x\n",
 630                        drive->name, stat);
 631                rq->current_nr_sectors++;
 632                return DRIVER(drive)->error(drive, "task_in_intr", stat);
 633        }
 634        if (!rq->current_nr_sectors)
 635                if (!DRIVER(drive)->end_request(drive, 1))
 636                        return ide_stopped;
 637
 638        if (--rq->current_nr_sectors <= 0)
 639                if (!DRIVER(drive)->end_request(drive, 1))
 640                        return ide_stopped;
 641#endif
 642
 643        pBuf = task_map_rq(rq, &flags);
 644        DTF("Read: %p, rq->current_nr_sectors: %d, stat: %02x\n",
 645                pBuf, (int) rq->current_nr_sectors, stat);
 646        taskfile_input_data(drive, pBuf, SECTOR_WORDS);
 647        task_unmap_rq(rq, pBuf, &flags);
 648        /*
 649         * FIXME :: We really can not legally get a new page/bh
 650         * regardless, if this is the end of our segment.
 651         * BH walking or segment can only be updated after we have a good
 652         * hwif->INB(IDE_STATUS_REG); return.
 653         */
 654        if (--rq->current_nr_sectors <= 0)
 655                if (!DRIVER(drive)->end_request(drive, 1))
 656                        return ide_stopped;
 657        /*
 658         * ERM, it is techincally legal to leave/exit here but it makes
 659         * a mess of the code ...
 660         */
 661        if (HWGROUP(drive)->handler == NULL)
 662                ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
 663        return ide_started;
 664}
 665
 666EXPORT_SYMBOL(task_in_intr);
 667
 668/*
 669 * Handler for command with Read Multiple
 670 */
 671ide_startstop_t task_mulin_intr (ide_drive_t *drive)
 672{
 673        ide_hwif_t *hwif        = HWIF(drive);
 674        struct request *rq      = HWGROUP(drive)->rq;
 675        char *pBuf              = NULL;
 676        unsigned int msect      = drive->mult_count;
 677        unsigned int nsect;
 678        unsigned long flags;
 679        u8 stat;
 680
 681        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
 682                if (stat & (ERR_STAT|DRQ_STAT)) {
 683                        if (!rq->bh) {
 684                                rq->current_nr_sectors += drive->mult_count;
 685                                /*
 686                                 * NOTE: could rewind beyond beginning :-/
 687                                 */
 688                        } else {
 689                                printk("%s: MULTI-READ assume all data " \
 690                                        "transfered is bad status=0x%02x\n",
 691                                        drive->name, stat);
 692                        }
 693                        return DRIVER(drive)->error(drive, "task_mulin_intr", stat);
 694                }
 695                /* no data yet, so wait for another interrupt */
 696                if (HWGROUP(drive)->handler == NULL)
 697                        ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
 698                return ide_started;
 699        }
 700
 701        do {
 702                nsect = rq->current_nr_sectors;
 703                if (nsect > msect)
 704                        nsect = msect;
 705                pBuf = task_map_rq(rq, &flags);
 706                DTF("Multiread: %p, nsect: %d, msect: %d, " \
 707                        " rq->current_nr_sectors: %d\n",
 708                        pBuf, nsect, msect, rq->current_nr_sectors);
 709                taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
 710                task_unmap_rq(rq, pBuf, &flags);
 711                rq->errors = 0;
 712                rq->current_nr_sectors -= nsect;
 713                msect -= nsect;
 714                /*
 715                 * FIXME :: We really can not legally get a new page/bh
 716                 * regardless, if this is the end of our segment.
 717                 * BH walking or segment can only be updated after we have a
 718                 * good hwif->INB(IDE_STATUS_REG); return.
 719                 */
 720                if (!rq->current_nr_sectors) {
 721                        if (!DRIVER(drive)->end_request(drive, 1))
 722                                return ide_stopped;
 723                }
 724        } while (msect);
 725        if (HWGROUP(drive)->handler == NULL)
 726                ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
 727        return ide_started;
 728}
 729
 730EXPORT_SYMBOL(task_mulin_intr);
 731
 732/*
 733 * VERIFY ME before 2.4 ... unexpected race is possible based on details
 734 * RMK with 74LS245/373/374 TTL buffer logic because of passthrough.
 735 */
 736ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
 737{
 738        char *pBuf              = NULL;
 739        unsigned long flags;
 740        ide_startstop_t startstop;
 741
 742        if (ide_wait_stat(&startstop, drive, DATA_READY,
 743                        drive->bad_wstat, WAIT_DRQ)) {
 744                printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n",
 745                        drive->name,
 746                        drive->addressing ? "_EXT" : "");
 747                return startstop;
 748        }
 749        /* For Write_sectors we need to stuff the first sector */
 750        pBuf = task_map_rq(rq, &flags);
 751        taskfile_output_data(drive, pBuf, SECTOR_WORDS);
 752        rq->current_nr_sectors--;
 753        task_unmap_rq(rq, pBuf, &flags);
 754        return ide_started;
 755}
 756
 757EXPORT_SYMBOL(pre_task_out_intr);
 758
 759/*
 760 * Handler for command with PIO data-out phase WRITE
 761 *
 762 * WOOHOO this is a CORRECT STATE DIAGRAM NOW, <andre@linux-ide.org>
 763 */
 764ide_startstop_t task_out_intr (ide_drive_t *drive)
 765{
 766        ide_hwif_t *hwif        = HWIF(drive);
 767        struct request *rq      = HWGROUP(drive)->rq;
 768        char *pBuf              = NULL;
 769        unsigned long flags;
 770        u8 stat;
 771
 772        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), DRIVE_READY, drive->bad_wstat)) {
 773                DTF("%s: WRITE attempting to recover last " \
 774                        "sector counter status=0x%02x\n",
 775                        drive->name, stat);
 776                rq->current_nr_sectors++;
 777                return DRIVER(drive)->error(drive, "task_out_intr", stat);
 778        }
 779        /*
 780         * Safe to update request for partial completions.
 781         * We have a good STATUS CHECK!!!
 782         */
 783        if (!rq->current_nr_sectors)
 784                if (!DRIVER(drive)->end_request(drive, 1))
 785                        return ide_stopped;
 786        if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
 787                rq = HWGROUP(drive)->rq;
 788                pBuf = task_map_rq(rq, &flags);
 789                DTF("write: %p, rq->current_nr_sectors: %d\n",
 790                        pBuf, (int) rq->current_nr_sectors);
 791                taskfile_output_data(drive, pBuf, SECTOR_WORDS);
 792                task_unmap_rq(rq, pBuf, &flags);
 793                rq->errors = 0;
 794                rq->current_nr_sectors--;
 795        }
 796        if (HWGROUP(drive)->handler == NULL)
 797                ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
 798        return ide_started;
 799}
 800
 801EXPORT_SYMBOL(task_out_intr);
 802
 803#undef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
 804
 805ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
 806{
 807#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
 808        ide_hwif_t *hwif                = HWIF(drive);
 809        char *pBuf                      = NULL;
 810        unsigned int nsect = 0, msect   = drive->mult_count;
 811        u8 stat;
 812        unsigned long flags;
 813#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 814
 815        ide_task_t *args = rq->special;
 816        ide_startstop_t startstop;
 817
 818#if 0
 819        /*
 820         * assign private copy for multi-write
 821         */
 822        memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
 823#endif
 824
 825        if (ide_wait_stat(&startstop, drive, DATA_READY,
 826                        drive->bad_wstat, WAIT_DRQ)) {
 827                printk(KERN_ERR "%s: no DRQ after issuing %s\n",
 828                        drive->name,
 829                        drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE");
 830                return startstop;
 831        }
 832#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
 833
 834        do {
 835                nsect = rq->current_nr_sectors;
 836                if (nsect > msect)
 837                        nsect = msect;
 838                pBuf = task_map_rq(rq, &flags);
 839                DTF("Pre-Multiwrite: %p, nsect: %d, msect: %d, " \
 840                        "rq->current_nr_sectors: %ld\n",
 841                        pBuf, nsect, msect, rq->current_nr_sectors);
 842                msect -= nsect;
 843                taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
 844                task_unmap_rq(rq, pBuf, &flags);
 845                rq->current_nr_sectors -= nsect;
 846                if (!rq->current_nr_sectors) {
 847                        if (!DRIVER(drive)->end_request(drive, 1))
 848                                if (!rq->bh) {
 849                                        stat = hwif->INB(IDE_STATUS_REG);
 850                                        return ide_stopped;
 851                                }
 852                }
 853        } while (msect);
 854        rq->errors = 0;
 855        return ide_started;
 856#else /* ! ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 857        if (!(drive_is_ready(drive))) {
 858                int i;
 859                for (i=0; i<100; i++) {
 860                        if (drive_is_ready(drive))
 861                                break;
 862                }
 863        }
 864
 865        /*
 866         * WARNING :: if the drive as not acked good status we may not
 867         * move the DATA-TRANSFER T-Bar as BSY != 0. <andre@linux-ide.org>
 868         */
 869        return args->handler(drive);
 870#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 871}
 872
 873EXPORT_SYMBOL(pre_task_mulout_intr);
 874
 875/*
 876 * FIXME before enabling in 2.4 ... DATA integrity issue upon error.
 877 */
 878/*
 879 * Handler for command write multiple
 880 * Called directly from execute_drive_cmd for the first bunch of sectors,
 881 * afterwards only by the ISR
 882 */
 883ide_startstop_t task_mulout_intr (ide_drive_t *drive)
 884{
 885        ide_hwif_t *hwif                = HWIF(drive);
 886        u8 stat                         = hwif->INB(IDE_STATUS_REG);
 887        struct request *rq              = HWGROUP(drive)->rq;
 888        char *pBuf                      = NULL;
 889        ide_startstop_t startstop       = ide_stopped;
 890        unsigned int msect              = drive->mult_count;
 891        unsigned int nsect;
 892        unsigned long flags;
 893
 894        /*
 895         * (ks/hs): Handle last IRQ on multi-sector transfer,
 896         * occurs after all data was sent in this chunk
 897         */
 898        if (rq->current_nr_sectors == 0) {
 899                if (stat & (ERR_STAT|DRQ_STAT)) {
 900                        if (!rq->bh) {
 901                                rq->current_nr_sectors += drive->mult_count;
 902                                /*
 903                                 * NOTE: could rewind beyond beginning :-/
 904                                 */
 905                        } else {
 906                                printk(KERN_ERR "%s: MULTI-WRITE assume all data " \
 907                                        "transfered is bad status=0x%02x\n",
 908                                        drive->name, stat);
 909                        }
 910                        return DRIVER(drive)->error(drive, "task_mulout_intr", stat);
 911                }
 912                if (!rq->bh)
 913                        DRIVER(drive)->end_request(drive, 1);
 914                return startstop;
 915        }
 916        /*
 917         * DON'T be lazy code the above and below togather !!!
 918         */
 919        if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
 920                if (stat & (ERR_STAT|DRQ_STAT)) {
 921                        if (!rq->bh) {
 922                                rq->current_nr_sectors += drive->mult_count;
 923                                /*
 924                                 * NOTE: could rewind beyond beginning :-/
 925                                 */
 926                        } else {
 927                                printk(KERN_ERR "%s: MULTI-WRITE assume all data " \
 928                                        "transfered is bad status=0x%02x\n",
 929                                        drive->name, stat);
 930                        }
 931                        return DRIVER(drive)->error(drive, "task_mulout_intr", stat);
 932                }
 933                /* no data yet, so wait for another interrupt */
 934                if (HWGROUP(drive)->handler == NULL)
 935                        ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
 936                return ide_started;
 937        }
 938
 939#ifndef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
 940        if (HWGROUP(drive)->handler != NULL) {
 941                unsigned long lflags;
 942                spin_lock_irqsave(&io_request_lock, lflags);
 943                HWGROUP(drive)->handler = NULL;
 944                del_timer(&HWGROUP(drive)->timer);
 945                spin_unlock_irqrestore(&io_request_lock, lflags);
 946        }
 947#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 948
 949        do {
 950                nsect = rq->current_nr_sectors;
 951                if (nsect > msect)
 952                        nsect = msect;
 953                pBuf = task_map_rq(rq, &flags);
 954                DTF("Multiwrite: %p, nsect: %d, msect: %d, " \
 955                        "rq->current_nr_sectors: %ld\n",
 956                        pBuf, nsect, msect, rq->current_nr_sectors);
 957                msect -= nsect;
 958                taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
 959                task_unmap_rq(rq, pBuf, &flags);
 960                rq->current_nr_sectors -= nsect;
 961                /*
 962                 * FIXME :: We really can not legally get a new page/bh
 963                 * regardless, if this is the end of our segment.
 964                 * BH walking or segment can only be updated after we
 965                 * have a good  hwif->INB(IDE_STATUS_REG); return.
 966                 */
 967                if (!rq->current_nr_sectors) {
 968                        if (!DRIVER(drive)->end_request(drive, 1))
 969                                if (!rq->bh)
 970                                        return ide_stopped;
 971                }
 972        } while (msect);
 973        rq->errors = 0;
 974        if (HWGROUP(drive)->handler == NULL)
 975                ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
 976        return ide_started;
 977}
 978
 979EXPORT_SYMBOL(task_mulout_intr);
 980
 981/* Called by internal to feature out type of command being called */
 982//ide_pre_handler_t * ide_pre_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile)
 983ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
 984{
 985        switch(taskfile->command) {
 986                                /* IDE_DRIVE_TASK_RAW_WRITE */
 987                case CFA_WRITE_MULTI_WO_ERASE:
 988        //      case WIN_WRITE_LONG:
 989        //      case WIN_WRITE_LONG_ONCE:
 990                case WIN_MULTWRITE:
 991                case WIN_MULTWRITE_EXT:
 992                        return &pre_task_mulout_intr;
 993                        
 994                                /* IDE_DRIVE_TASK_OUT */
 995                case WIN_WRITE:
 996        //      case WIN_WRITE_ONCE:
 997                case WIN_WRITE_EXT:
 998                case WIN_WRITE_VERIFY:
 999                case WIN_WRITE_BUFFER:
1000                case CFA_WRITE_SECT_WO_ERASE:
1001                case WIN_DOWNLOAD_MICROCODE:
1002                        return &pre_task_out_intr;
1003                                /* IDE_DRIVE_TASK_OUT */
1004                case WIN_SMART:
1005                        if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
1006                                return &pre_task_out_intr;
1007                case WIN_WRITEDMA:
1008        //      case WIN_WRITEDMA_ONCE:
1009                case WIN_WRITEDMA_QUEUED:
1010                case WIN_WRITEDMA_EXT:
1011                case WIN_WRITEDMA_QUEUED_EXT:
1012                                /* IDE_DRIVE_TASK_OUT */
1013                default:
1014                        break;
1015        }
1016        return(NULL);
1017}
1018
1019EXPORT_SYMBOL(ide_pre_handler_parser);
1020
1021/* Called by internal to feature out type of command being called */
1022//ide_handler_t * ide_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile)
1023ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
1024{
1025        switch(taskfile->command) {
1026                case WIN_IDENTIFY:
1027                case WIN_PIDENTIFY:
1028                case CFA_TRANSLATE_SECTOR:
1029                case WIN_READ_BUFFER:
1030                case WIN_READ:
1031        //      case WIN_READ_ONCE:
1032                case WIN_READ_EXT:
1033                        return &task_in_intr;
1034                case WIN_SECURITY_DISABLE:
1035                case WIN_SECURITY_ERASE_UNIT:
1036                case WIN_SECURITY_SET_PASS:
1037                case WIN_SECURITY_UNLOCK:
1038                case WIN_DOWNLOAD_MICROCODE:
1039                case CFA_WRITE_SECT_WO_ERASE:
1040                case WIN_WRITE_BUFFER:
1041                case WIN_WRITE_VERIFY:
1042                case WIN_WRITE:
1043        //      case WIN_WRITE_ONCE:    
1044                case WIN_WRITE_EXT:
1045                        return &task_out_intr;
1046        //      case WIN_READ_LONG:
1047        //      case WIN_READ_LONG_ONCE:
1048                case WIN_MULTREAD:
1049                case WIN_MULTREAD_EXT:
1050                        return &task_mulin_intr;
1051        //      case WIN_WRITE_LONG:
1052        //      case WIN_WRITE_LONG_ONCE:
1053                case CFA_WRITE_MULTI_WO_ERASE:
1054                case WIN_MULTWRITE:
1055                case WIN_MULTWRITE_EXT:
1056                        return &task_mulout_intr;
1057                case WIN_SMART:
1058                        switch(taskfile->feature) {
1059                                case SMART_READ_VALUES:
1060                                case SMART_READ_THRESHOLDS:
1061                                case SMART_READ_LOG_SECTOR:
1062                                        return &task_in_intr;
1063                                case SMART_WRITE_LOG_SECTOR:
1064                                        return &task_out_intr;
1065                                default:
1066                                        return &task_no_data_intr;
1067                        }
1068                case CFA_REQ_EXT_ERROR_CODE:
1069                case CFA_ERASE_SECTORS:
1070                case WIN_VERIFY:
1071        //      case WIN_VERIFY_ONCE:
1072                case WIN_VERIFY_EXT:
1073                case WIN_SEEK:
1074                        return &task_no_data_intr;
1075                case WIN_SPECIFY:
1076                        return &set_geometry_intr;
1077                case WIN_RECAL:
1078        //      case WIN_RESTORE:
1079                        return &recal_intr;
1080                case WIN_NOP:
1081                case WIN_DIAGNOSE:
1082                case WIN_FLUSH_CACHE:
1083                case WIN_FLUSH_CACHE_EXT:
1084                case WIN_STANDBYNOW1:
1085                case WIN_STANDBYNOW2:
1086                case WIN_SLEEPNOW1:
1087                case WIN_SLEEPNOW2:
1088                case WIN_SETIDLE1:
1089                case WIN_CHECKPOWERMODE1:
1090                case WIN_CHECKPOWERMODE2:
1091                case WIN_GETMEDIASTATUS:
1092                case WIN_MEDIAEJECT:
1093                        return &task_no_data_intr;
1094                case WIN_SETMULT:
1095                        return &set_multmode_intr;
1096                case WIN_READ_NATIVE_MAX:
1097                case WIN_SET_MAX:
1098                case WIN_READ_NATIVE_MAX_EXT:
1099                case WIN_SET_MAX_EXT:
1100                case WIN_SECURITY_ERASE_PREPARE:
1101                case WIN_SECURITY_FREEZE_LOCK:
1102                case WIN_DOORLOCK:
1103                case WIN_DOORUNLOCK:
1104                case WIN_SETFEATURES:
1105                        return &task_no_data_intr;
1106                case DISABLE_SEAGATE:
1107                case EXABYTE_ENABLE_NEST:
1108                        return &task_no_data_intr;
1109#ifdef CONFIG_BLK_DEV_IDEDMA
1110                case WIN_READDMA:
1111        //      case WIN_READDMA_ONCE:
1112                case WIN_IDENTIFY_DMA:
1113                case WIN_READDMA_QUEUED:
1114                case WIN_READDMA_EXT:
1115                case WIN_READDMA_QUEUED_EXT:
1116                case WIN_WRITEDMA:
1117        //      case WIN_WRITEDMA_ONCE:
1118                case WIN_WRITEDMA_QUEUED:
1119                case WIN_WRITEDMA_EXT:
1120                case WIN_WRITEDMA_QUEUED_EXT:
1121#endif
1122                case WIN_FORMAT:
1123                case WIN_INIT:
1124                case WIN_DEVICE_RESET:
1125                case WIN_QUEUED_SERVICE:
1126                case WIN_PACKETCMD:
1127                default:
1128                        return(NULL);
1129        }       
1130}
1131
1132EXPORT_SYMBOL(ide_handler_parser);
1133
1134ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
1135{
1136        switch(taskfile->command) {
1137                case WIN_SPECIFY:       /* set_geometry_intr */
1138                case WIN_RESTORE:       /* recal_intr */
1139                case WIN_SETMULT:       /* set_multmode_intr */
1140                default:
1141                        return(NULL);
1142        }
1143}
1144
1145EXPORT_SYMBOL(ide_post_handler_parser);
1146
1147/* Called by ioctl to feature out type of command being called */
1148int ide_cmd_type_parser (ide_task_t *args)
1149{
1150
1151        task_struct_t *taskfile = (task_struct_t *) args->tfRegister;
1152        hob_struct_t *hobfile   = (hob_struct_t *) args->hobRegister;
1153
1154        args->prehandler        = ide_pre_handler_parser(taskfile, hobfile);
1155        args->handler           = ide_handler_parser(taskfile, hobfile);
1156        args->posthandler       = ide_post_handler_parser(taskfile, hobfile);
1157
1158        switch(args->tfRegister[IDE_COMMAND_OFFSET]) {
1159                case WIN_IDENTIFY:
1160                case WIN_PIDENTIFY:
1161                        return IDE_DRIVE_TASK_IN;
1162                case CFA_TRANSLATE_SECTOR:
1163                case WIN_READ:
1164        //      case WIN_READ_ONCE:
1165                case WIN_READ_EXT:
1166                case WIN_READ_BUFFER:
1167                        return IDE_DRIVE_TASK_IN;
1168                case WIN_WRITE:
1169        //      case WIN_WRITE_ONCE:
1170                case WIN_WRITE_EXT:
1171                case WIN_WRITE_VERIFY:
1172                case WIN_WRITE_BUFFER:
1173                case CFA_WRITE_SECT_WO_ERASE:
1174                case WIN_DOWNLOAD_MICROCODE:
1175                        return IDE_DRIVE_TASK_RAW_WRITE;
1176        //      case WIN_READ_LONG:
1177        //      case WIN_READ_LONG_ONCE:
1178                case WIN_MULTREAD:
1179                case WIN_MULTREAD_EXT:
1180                        return IDE_DRIVE_TASK_IN;
1181        //      case WIN_WRITE_LONG:
1182        //      case WIN_WRITE_LONG_ONCE:
1183                case CFA_WRITE_MULTI_WO_ERASE:
1184                case WIN_MULTWRITE:
1185                case WIN_MULTWRITE_EXT:
1186                        return IDE_DRIVE_TASK_RAW_WRITE;
1187                case WIN_SECURITY_DISABLE:
1188                case WIN_SECURITY_ERASE_UNIT:
1189                case WIN_SECURITY_SET_PASS:
1190                case WIN_SECURITY_UNLOCK:
1191                        return IDE_DRIVE_TASK_OUT;
1192                case WIN_SMART:
1193                        args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
1194                        args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
1195                        switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
1196                                case SMART_READ_VALUES:
1197                                case SMART_READ_THRESHOLDS:
1198                                case SMART_READ_LOG_SECTOR:
1199                                        return IDE_DRIVE_TASK_IN;
1200                                case SMART_WRITE_LOG_SECTOR:
1201                                        return IDE_DRIVE_TASK_OUT;
1202                                default:
1203                                        return IDE_DRIVE_TASK_NO_DATA;
1204                        }
1205#ifdef CONFIG_BLK_DEV_IDEDMA
1206                case WIN_READDMA:
1207        //      case WIN_READDMA_ONCE:
1208                case WIN_IDENTIFY_DMA:
1209                case WIN_READDMA_QUEUED:
1210                case WIN_READDMA_EXT:
1211                case WIN_READDMA_QUEUED_EXT:
1212                        return IDE_DRIVE_TASK_IN;
1213                case WIN_WRITEDMA:
1214        //      case WIN_WRITEDMA_ONCE:
1215                case WIN_WRITEDMA_QUEUED:
1216                case WIN_WRITEDMA_EXT:
1217                case WIN_WRITEDMA_QUEUED_EXT:
1218                        return IDE_DRIVE_TASK_RAW_WRITE;
1219#endif
1220                case WIN_SETFEATURES:
1221                        switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
1222                                case SETFEATURES_EN_8BIT:
1223                                case SETFEATURES_EN_WCACHE:
1224                                        return IDE_DRIVE_TASK_NO_DATA;
1225                                case SETFEATURES_XFER:
1226                                        return IDE_DRIVE_TASK_SET_XFER;
1227                                case SETFEATURES_DIS_DEFECT:
1228                                case SETFEATURES_EN_APM:
1229                                case SETFEATURES_DIS_MSN:
1230                                case SETFEATURES_DIS_RETRY:
1231                                case SETFEATURES_EN_AAM:
1232                                case SETFEATURES_RW_LONG:
1233                                case SETFEATURES_SET_CACHE:
1234                                case SETFEATURES_DIS_RLA:
1235                                case SETFEATURES_EN_RI:
1236                                case SETFEATURES_EN_SI:
1237                                case SETFEATURES_DIS_RPOD:
1238                                case SETFEATURES_DIS_WCACHE:
1239                                case SETFEATURES_EN_DEFECT:
1240                                case SETFEATURES_DIS_APM:
1241                                case SETFEATURES_EN_ECC:
1242                                case SETFEATURES_EN_MSN:
1243                                case SETFEATURES_EN_RETRY:
1244                                case SETFEATURES_EN_RLA:
1245                                case SETFEATURES_PREFETCH:
1246                                case SETFEATURES_4B_RW_LONG:
1247                                case SETFEATURES_DIS_AAM:
1248                                case SETFEATURES_EN_RPOD:
1249                                case SETFEATURES_DIS_RI:
1250                                case SETFEATURES_DIS_SI:
1251                                default:
1252                                        return IDE_DRIVE_TASK_NO_DATA;
1253                        }
1254                case WIN_NOP:
1255                case CFA_REQ_EXT_ERROR_CODE:
1256                case CFA_ERASE_SECTORS:
1257                case WIN_VERIFY:
1258        //      case WIN_VERIFY_ONCE:
1259                case WIN_VERIFY_EXT:
1260                case WIN_SEEK:
1261                case WIN_SPECIFY:
1262                case WIN_RESTORE:
1263                case WIN_DIAGNOSE:
1264                case WIN_FLUSH_CACHE:
1265                case WIN_FLUSH_CACHE_EXT:
1266                case WIN_STANDBYNOW1:
1267                case WIN_STANDBYNOW2:
1268                case WIN_SLEEPNOW1:
1269                case WIN_SLEEPNOW2:
1270                case WIN_SETIDLE1:
1271                case DISABLE_SEAGATE:
1272                case WIN_CHECKPOWERMODE1:
1273                case WIN_CHECKPOWERMODE2:
1274                case WIN_GETMEDIASTATUS:
1275                case WIN_MEDIAEJECT:
1276                case WIN_SETMULT:
1277                case WIN_READ_NATIVE_MAX:
1278                case WIN_SET_MAX:
1279                case WIN_READ_NATIVE_MAX_EXT:
1280                case WIN_SET_MAX_EXT:
1281                case WIN_SECURITY_ERASE_PREPARE:
1282                case WIN_SECURITY_FREEZE_LOCK:
1283                case EXABYTE_ENABLE_NEST:
1284                case WIN_DOORLOCK:
1285                case WIN_DOORUNLOCK:
1286                        return IDE_DRIVE_TASK_NO_DATA;
1287                case WIN_FORMAT:
1288                case WIN_INIT:
1289                case WIN_DEVICE_RESET:
1290                case WIN_QUEUED_SERVICE:
1291                case WIN_PACKETCMD:
1292                default:
1293                        return IDE_DRIVE_TASK_INVALID;
1294        }
1295}
1296
1297EXPORT_SYMBOL(ide_cmd_type_parser);
1298
1299/*
1300 * This function is intended to be used prior to invoking ide_do_drive_cmd().
1301 */
1302void ide_init_drive_taskfile (struct request *rq)
1303{
1304        memset(rq, 0, sizeof(*rq));
1305        rq->cmd = IDE_DRIVE_TASK_NO_DATA;
1306}
1307
1308EXPORT_SYMBOL(ide_init_drive_taskfile);
1309
1310#if 1
1311
1312int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
1313{
1314        struct request rq;
1315
1316        ide_init_drive_taskfile(&rq);
1317        rq.cmd = IDE_DRIVE_TASKFILE;
1318        rq.buffer = buf;
1319
1320        /*
1321         * (ks) We transfer currently only whole sectors.
1322         * This is suffient for now.  But, it would be great,
1323         * if we would find a solution to transfer any size.
1324         * To support special commands like READ LONG.
1325         */
1326        if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
1327                if (data_size == 0)
1328                        rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
1329                /*      rq.hard_cur_sectors     */
1330                else
1331                        rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE;
1332                /*      rq.hard_cur_sectors     */
1333        }
1334
1335        if (args->tf_out_flags.all == 0) {
1336                /*
1337                 * clean up kernel settings for driver sanity, regardless.
1338                 * except for discrete diag services.
1339                 */
1340                args->posthandler = ide_post_handler_parser(
1341                                (struct hd_drive_task_hdr *) args->tfRegister,
1342                                (struct hd_drive_hob_hdr *) args->hobRegister);
1343
1344        }
1345        rq.special = args;
1346        return ide_do_drive_cmd(drive, &rq, ide_wait);
1347}
1348
1349#else
1350
1351int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
1352{
1353        struct request *rq;
1354        unsigned long flags;
1355        ide_hwgroup_t *hwgroup = HWGROUP(drive);
1356        unsigned int major = HWIF(drive)->major;
1357        struct list_head *queue_head = &drive->queue.queue_head;
1358        DECLARE_COMPLETION(wait);
1359
1360        if (HWIF(drive)->chipset == ide_pdc4030 && buf != NULL)
1361                return -ENOSYS; /* special drive cmds not supported */
1362
1363        memset(rq, 0, sizeof(*rq));
1364        rq->cmd = IDE_DRIVE_TASKFILE;
1365        rq->buffer = buf;
1366
1367        /*
1368         * (ks) We transfer currently only whole sectors.
1369         * This is suffient for now.  But, it would be great,
1370         * if we would find a solution to transfer any size.
1371         * To support special commands like READ LONG.
1372         */
1373        if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
1374                if (data_size == 0) {
1375                        ata_nsector_t nsector;
1376                        nsector.b.low = args->hobRegister[IDE_NSECTOR_OFFSET_HOB];
1377                        nsector.b.high = args->tfRegister[IDE_NSECTOR_OFFSET];
1378                        rq.nr_sectors = nsector.all;
1379                } else {
1380                        rq.nr_sectors = data_size / SECTOR_SIZE;
1381                }
1382                rq.current_nr_sectors = rq.nr_sectors;
1383        //      rq.hard_cur_sectors = rq.nr_sectors;
1384        }
1385
1386        if (args->tf_out_flags.all == 0) {
1387                /*
1388                 * clean up kernel settings for driver sanity, regardless.
1389                 * except for discrete diag services.
1390                 */
1391                args->posthandler = ide_post_handler_parser(
1392                                (struct hd_drive_task_hdr *) args->tfRegister,
1393                                (struct hd_drive_hob_hdr *) args->hobRegister);
1394        }
1395        rq->special = args;
1396        rq->errors = 0;
1397        rq->rq_status = RQ_ACTIVE;
1398        rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
1399        rq->waiting = &wait;
1400
1401        spin_lock_irqsave(&io_request_lock, flags);
1402        queue_head = queue_head->prev;
1403        list_add(&rq->queue, queue_head);
1404        ide_do_request(hwgroup, 0);
1405        spin_unlock_irqrestore(&io_request_lock, flags);
1406
1407        wait_for_completion(&wait);     /* wait for it to be serviced */
1408        return rq->errors ? -EIO : 0;   /* return -EIO if errors */
1409}
1410
1411#endif
1412
1413EXPORT_SYMBOL(ide_diag_taskfile);
1414
1415int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
1416{
1417        return ide_diag_taskfile(drive, args, 0, buf);
1418}
1419
1420EXPORT_SYMBOL(ide_raw_taskfile);
1421        
1422#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
1423char * ide_ioctl_verbose (unsigned int cmd)
1424{
1425        return("unknown");
1426}
1427
1428char * ide_task_cmd_verbose (u8 task)
1429{
1430        return("unknown");
1431}
1432#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
1433
1434#define MAX_DMA         (256*SECTOR_WORDS)
1435
1436ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *);
1437ide_startstop_t flagged_task_no_data_intr(ide_drive_t *);
1438ide_startstop_t flagged_task_in_intr(ide_drive_t *);
1439ide_startstop_t flagged_task_mulin_intr(ide_drive_t *);
1440ide_startstop_t flagged_pre_task_out_intr(ide_drive_t *, struct request *);
1441ide_startstop_t flagged_task_out_intr(ide_drive_t *);
1442ide_startstop_t flagged_pre_task_mulout_intr(ide_drive_t *, struct request *);
1443ide_startstop_t flagged_task_mulout_intr(ide_drive_t *);
1444
1445int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
1446{
1447        ide_task_request_t      *req_task;
1448        ide_task_t              args;
1449        u8 *outbuf              = NULL;
1450        u8 *inbuf               = NULL;
1451        task_ioreg_t *argsptr   = args.tfRegister;
1452        task_ioreg_t *hobsptr   = args.hobRegister;
1453        int err                 = 0;
1454        int tasksize            = sizeof(struct ide_task_request_s);
1455        int taskin              = 0;
1456        int taskout             = 0;
1457        u8 io_32bit             = drive->io_32bit;
1458
1459//      printk("IDE Taskfile ...\n");
1460
1461        req_task = kmalloc(tasksize, GFP_KERNEL);
1462        if (req_task == NULL) return -ENOMEM;
1463        memset(req_task, 0, tasksize);
1464        if (copy_from_user(req_task, (void *) arg, tasksize)) {
1465                kfree(req_task);
1466                return -EFAULT;
1467        }
1468
1469        taskout = (int) req_task->out_size;
1470        taskin  = (int) req_task->in_size;
1471
1472        if (taskout) {
1473                int outtotal = tasksize;
1474                outbuf = kmalloc(taskout, GFP_KERNEL);
1475                if (outbuf == NULL) {
1476                        err = -ENOMEM;
1477                        goto abort;
1478                }
1479                memset(outbuf, 0, taskout);
1480                if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) {
1481                        err = -EFAULT;
1482                        goto abort;
1483                }
1484        }
1485
1486        if (taskin) {
1487                int intotal = tasksize + taskout;
1488                inbuf = kmalloc(taskin, GFP_KERNEL);
1489                if (inbuf == NULL) {
1490                        err = -ENOMEM;
1491                        goto abort;
1492                }
1493                memset(inbuf, 0, taskin);
1494                if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) {
1495                        err = -EFAULT;
1496                        goto abort;
1497                }
1498        }
1499
1500        memset(&args, 0, sizeof(ide_task_t));
1501        memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
1502        memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
1503
1504        args.tf_in_flags  = req_task->in_flags;
1505        args.tf_out_flags = req_task->out_flags;
1506        args.data_phase   = req_task->data_phase;
1507        args.command_type = req_task->req_cmd;
1508
1509#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
1510        DTF("%s: ide_ioctl_cmd %s:  ide_task_cmd %s\n",
1511                drive->name,
1512                ide_ioctl_verbose(cmd),
1513                ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET]));
1514#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
1515
1516        drive->io_32bit = 0;
1517        switch(req_task->data_phase) {
1518                case TASKFILE_OUT_DMAQ:
1519                case TASKFILE_OUT_DMA:
1520                        err = ide_diag_taskfile(drive, &args, taskout, outbuf);
1521                        break;
1522                case TASKFILE_IN_DMAQ:
1523                case TASKFILE_IN_DMA:
1524                        err = ide_diag_taskfile(drive, &args, taskin, inbuf);
1525                        break;
1526                case TASKFILE_IN_OUT:
1527#if 0
1528                        args.prehandler = &pre_task_out_intr;
1529                        args.handler = &task_out_intr;
1530                        args.posthandler = NULL;
1531                        err = ide_diag_taskfile(drive, &args, taskout, outbuf);
1532                        args.prehandler = NULL;
1533                        args.handler = &task_in_intr;
1534                        args.posthandler = NULL;
1535                        err = ide_diag_taskfile(drive, &args, taskin, inbuf);
1536                        break;
1537#else
1538                        err = -EFAULT;
1539                        goto abort;
1540#endif
1541                case TASKFILE_MULTI_OUT:
1542                        if (!drive->mult_count) {
1543                                /* (hs): give up if multcount is not set */
1544                                printk(KERN_ERR "%s: %s Multimode Write " \
1545                                        "multcount is not set\n",
1546                                        drive->name, __FUNCTION__);
1547                                err = -EPERM;
1548                                goto abort;
1549                        }
1550                        if (args.tf_out_flags.all != 0) {
1551                                args.prehandler = &flagged_pre_task_mulout_intr;
1552                                args.handler = &flagged_task_mulout_intr;
1553                        } else {
1554                                args.prehandler = &pre_task_mulout_intr;
1555                                args.handler = &task_mulout_intr;
1556                        }
1557                        err = ide_diag_taskfile(drive, &args, taskout, outbuf);
1558                        break;
1559                case TASKFILE_OUT:
1560                        if (args.tf_out_flags.all != 0) {
1561                                args.prehandler = &flagged_pre_task_out_intr;
1562                                args.handler    = &flagged_task_out_intr;
1563                        } else {
1564                                args.prehandler = &pre_task_out_intr;
1565                                args.handler = &task_out_intr;
1566                        }
1567                        err = ide_diag_taskfile(drive, &args, taskout, outbuf);
1568                        break;
1569                case TASKFILE_MULTI_IN:
1570                        if (!drive->mult_count) {
1571                                /* (hs): give up if multcount is not set */
1572                                printk(KERN_ERR "%s: %s Multimode Read failure " \
1573                                        "multcount is not set\n",
1574                                        drive->name, __FUNCTION__);
1575                                err = -EPERM;
1576                                goto abort;
1577                        }
1578                        if (args.tf_out_flags.all != 0) {
1579                                args.handler = &flagged_task_mulin_intr;
1580                        } else {
1581                                args.handler = &task_mulin_intr;
1582                        }
1583                        err = ide_diag_taskfile(drive, &args, taskin, inbuf);
1584                        break;
1585                case TASKFILE_IN:
1586                        if (args.tf_out_flags.all != 0) {
1587                                args.handler = &flagged_task_in_intr;
1588                        } else {
1589                                args.handler = &task_in_intr;
1590                        }
1591                        err = ide_diag_taskfile(drive, &args, taskin, inbuf);
1592                        break;
1593                case TASKFILE_NO_DATA:
1594                        if (args.tf_out_flags.all != 0) {
1595                                args.handler = &flagged_task_no_data_intr;
1596                        } else {
1597                                args.handler = &task_no_data_intr;
1598                        }
1599                        err = ide_diag_taskfile(drive, &args, 0, NULL);
1600                        break;
1601                default:
1602                        err = -EFAULT;
1603                        goto abort;
1604        }
1605
1606        memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
1607        memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
1608        req_task->in_flags  = args.tf_in_flags;
1609        req_task->out_flags = args.tf_out_flags;
1610
1611        if (copy_to_user((void *)arg, req_task, tasksize)) {
1612                err = -EFAULT;
1613                goto abort;
1614        }
1615        if (taskout) {
1616                int outtotal = tasksize;
1617                if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) {
1618                        err = -EFAULT;
1619                        goto abort;
1620                }
1621        }
1622        if (taskin) {
1623                int intotal = tasksize + taskout;
1624                if (copy_to_user((void *)arg+intotal, inbuf, taskin)) {
1625                        err = -EFAULT;
1626                        goto abort;
1627                }
1628        }
1629abort:
1630        kfree(req_task);
1631        if (outbuf != NULL)
1632                kfree(outbuf);
1633        if (inbuf != NULL)
1634                kfree(inbuf);
1635
1636//      printk("IDE Taskfile ioctl ended. rc = %i\n", err);
1637
1638        drive->io_32bit = io_32bit;
1639
1640        return err;
1641}
1642
1643EXPORT_SYMBOL(ide_taskfile_ioctl);
1644
1645int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
1646{
1647        struct request rq;
1648        u8 buffer[4];
1649
1650        if (!buf)
1651                buf = buffer;
1652        memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
1653        ide_init_drive_cmd(&rq);
1654        rq.buffer = buf;
1655        *buf++ = cmd;
1656        *buf++ = nsect;
1657        *buf++ = feature;
1658        *buf++ = sectors;
1659        return ide_do_drive_cmd(drive, &rq, ide_wait);
1660}
1661
1662EXPORT_SYMBOL(ide_wait_cmd);
1663
1664/*
1665 * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
1666 */
1667int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
1668{
1669#if 1
1670        int err = -EIO;
1671        u8 args[4], *argbuf = args;
1672        u8 xfer_rate = 0;
1673        int argsize = 4;
1674        ide_task_t tfargs;
1675
1676        if (NULL == (void *) arg) {
1677                struct request rq;
1678                ide_init_drive_cmd(&rq);
1679                return ide_do_drive_cmd(drive, &rq, ide_wait);
1680        }
1681
1682        if (copy_from_user(args, (void *)arg, 4))
1683                return -EFAULT;
1684
1685        memset(&tfargs, 0, sizeof(ide_task_t));
1686        tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
1687        tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
1688        tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
1689        tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
1690        tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
1691        tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
1692        tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
1693
1694        if (args[3]) {
1695                argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
1696                argbuf = kmalloc(argsize, GFP_KERNEL);
1697                if (argbuf == NULL)
1698                        return -ENOMEM;
1699                memcpy(argbuf, args, 4);
1700        }
1701        if (set_transfer(drive, &tfargs)) {
1702                xfer_rate = args[1];
1703                if (ide_ata66_check(drive, &tfargs))
1704                        goto abort;
1705        }
1706
1707        err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
1708
1709        if (!err && xfer_rate) {
1710                /* active-retuning-calls future */
1711                ide_set_xfer_rate(drive, xfer_rate);
1712                ide_driveid_update(drive);
1713        }
1714abort:
1715        if (copy_to_user((void *)arg, argbuf, argsize))
1716                err = -EFAULT;
1717        if (argsize > 4)
1718                kfree(argbuf);
1719        return err;
1720
1721#else
1722
1723        int err = 0;
1724        u8 args[4], *argbuf = args;
1725        u8 xfer_rate = 0;
1726        int argsize = 0;
1727        ide_task_t tfargs;
1728
1729        if (NULL == (void *) arg) {
1730                struct request rq;
1731                ide_init_drive_cmd(&rq);
1732                return ide_do_drive_cmd(drive, &rq, ide_wait);
1733        }
1734
1735        if (copy_from_user(args, (void *)arg, 4))
1736                return -EFAULT;
1737
1738        memset(&tfargs, 0, sizeof(ide_task_t));
1739        tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
1740        tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
1741        tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
1742        tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
1743        tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
1744        tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
1745        tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
1746
1747        if (args[3]) {
1748                argsize = (SECTOR_WORDS * 4 * args[3]);
1749                argbuf = kmalloc(argsize, GFP_KERNEL);
1750                if (argbuf == NULL)
1751                        return -ENOMEM;
1752        }
1753
1754        if (set_transfer(drive, &tfargs)) {
1755                xfer_rate = args[1];
1756                if (ide_ata66_check(drive, &tfargs))
1757                        goto abort;
1758        }
1759
1760        tfargs.command_type = ide_cmd_type_parser(&tfargs);
1761        err = ide_raw_taskfile(drive, &tfargs, argbuf);
1762
1763        if (!err && xfer_rate) {
1764                /* active-retuning-calls future */
1765                ide_set_xfer_rate(drive, xfer_rate);
1766                ide_driveid_update(drive);
1767        }
1768abort:
1769        args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET];
1770        args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET];
1771        args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET];
1772        args[3] = 0;
1773
1774        if (copy_to_user((void *)arg, argbuf, 4))
1775                err = -EFAULT;
1776        if (argbuf != NULL) {
1777                if (copy_to_user((void *)arg, argbuf + 4, argsize))
1778                        err = -EFAULT;
1779                kfree(argbuf);
1780        }
1781        return err;
1782
1783#endif
1784}
1785
1786EXPORT_SYMBOL(ide_cmd_ioctl);
1787
1788int ide_wait_cmd_task (ide_drive_t *drive, u8 *buf)
1789{
1790        struct request rq;
1791
1792        ide_init_drive_cmd(&rq);
1793        rq.cmd = IDE_DRIVE_TASK;
1794        rq.buffer = buf;
1795        return ide_do_drive_cmd(drive, &rq, ide_wait);
1796}
1797
1798EXPORT_SYMBOL(ide_wait_cmd_task);
1799
1800/*
1801 * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
1802 */
1803int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
1804{
1805        int err = 0;
1806        u8 args[7], *argbuf = args;
1807        int argsize = 7;
1808
1809        if (copy_from_user(args, (void *)arg, 7))
1810                return -EFAULT;
1811        err = ide_wait_cmd_task(drive, argbuf);
1812        if (copy_to_user((void *)arg, argbuf, argsize))
1813                err = -EFAULT;
1814        return err;
1815}
1816
1817EXPORT_SYMBOL(ide_task_ioctl);
1818
1819/*
1820 * NOTICE: This is additions from IBM to provide a discrete interface,
1821 * for selective taskregister access operations.  Nice JOB Klaus!!!
1822 * Glad to be able to work and co-develop this with you and IBM.
1823 */
1824ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
1825{
1826        ide_hwif_t *hwif        = HWIF(drive);
1827        task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
1828        hob_struct_t *hobfile   = (hob_struct_t *) task->hobRegister;
1829#if DEBUG_TASKFILE
1830        u8 status;
1831#endif
1832
1833
1834#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
1835        void debug_taskfile(drive, task);
1836#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
1837
1838        /*
1839         * (ks) Check taskfile in/out flags.
1840         * If set, then execute as it is defined.
1841         * If not set, then define default settings.
1842         * The default values are:
1843         *      write and read all taskfile registers (except data) 
1844         *      write and read the hob registers (sector,nsector,lcyl,hcyl)
1845         */
1846        if (task->tf_out_flags.all == 0) {
1847                task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
1848                if (drive->addressing == 1)
1849                        task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8);
1850        }
1851
1852        if (task->tf_in_flags.all == 0) {
1853                task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
1854                if (drive->addressing == 1)
1855                        task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS  << 8);
1856        }
1857
1858        /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
1859        if (IDE_CONTROL_REG)
1860                /* clear nIEN */
1861                hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
1862        SELECT_MASK(drive, 0);
1863
1864#if DEBUG_TASKFILE
1865        status = hwif->INB(IDE_STATUS_REG);
1866        if (status & 0x80) {
1867                printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status);
1868                udelay(100);
1869                status = hwif->INB(IDE_STATUS_REG);
1870                printk("flagged_taskfile -> Status = %02x\n", status);
1871        }
1872#endif
1873
1874        if (task->tf_out_flags.b.data) {
1875                u16 data =  taskfile->data + (hobfile->data << 8);
1876                hwif->OUTW(data, IDE_DATA_REG);
1877        }
1878
1879        /* (ks) send hob registers first */
1880        if (task->tf_out_flags.b.nsector_hob)
1881                hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
1882        if (task->tf_out_flags.b.sector_hob)
1883                hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
1884        if (task->tf_out_flags.b.lcyl_hob)
1885                hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
1886        if (task->tf_out_flags.b.hcyl_hob)
1887                hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
1888
1889        /* (ks) Send now the standard registers */
1890        if (task->tf_out_flags.b.error_feature)
1891                hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
1892        /* refers to number of sectors to transfer */
1893        if (task->tf_out_flags.b.nsector)
1894                hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
1895        /* refers to sector offset or start sector */
1896        if (task->tf_out_flags.b.sector)
1897                hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
1898        if (task->tf_out_flags.b.lcyl)
1899                hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
1900        if (task->tf_out_flags.b.hcyl)
1901                hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
1902
1903        /*
1904         * (ks) In the flagged taskfile approch, we will used all specified
1905         * registers and the register value will not be changed. Except the
1906         * select bit (master/slave) in the drive_head register. We must make
1907         * sure that the desired drive is selected.
1908         */
1909        hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
1910        switch(task->data_phase) {
1911
1912                case TASKFILE_OUT_DMAQ:
1913                case TASKFILE_OUT_DMA:
1914                        hwif->ide_dma_write(drive);
1915                        break;
1916
1917                case TASKFILE_IN_DMAQ:
1918                case TASKFILE_IN_DMA:
1919                        hwif->ide_dma_read(drive);
1920                        break;
1921
1922                default:
1923                        if (task->handler == NULL)
1924                                return ide_stopped;
1925
1926                        /* Issue the command */
1927                        ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
1928                        if (task->prehandler != NULL)
1929                                return task->prehandler(drive, HWGROUP(drive)->rq);
1930        }
1931
1932        return ide_started;
1933}
1934
1935EXPORT_SYMBOL(flagged_taskfile);
1936
1937ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive)
1938{
1939        ide_hwif_t *hwif = HWIF(drive);
1940        u8 stat;
1941
1942        local_irq_enable();
1943
1944        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT)) {
1945                if (stat & ERR_STAT) {
1946                        return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat);
1947                }
1948                /*
1949                 * (ks) Unexpected ATA data phase detected.
1950                 * This should not happen. But, it can !
1951                 * I am not sure, which function is best to clean up
1952                 * this situation.  I choose: ide_error(...)
1953                 */
1954                return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); 
1955        }
1956
1957        ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
1958
1959        return ide_stopped;
1960}
1961
1962/*
1963 * Handler for command with PIO data-in phase
1964 */
1965ide_startstop_t flagged_task_in_intr (ide_drive_t *drive)
1966{
1967        ide_hwif_t *hwif        = HWIF(drive);
1968        u8 stat                 = hwif->INB(IDE_STATUS_REG);
1969        struct request *rq      = HWGROUP(drive)->rq;
1970        char *pBuf              = NULL;
1971        int retries             = 5;
1972
1973        if (rq->current_nr_sectors == 0) 
1974                return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); 
1975
1976        if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
1977                if (stat & ERR_STAT) {
1978                        return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat);
1979                }
1980                /*
1981                 * (ks) Unexpected ATA data phase detected.
1982                 * This should not happen. But, it can !
1983                 * I am not sure, which function is best to clean up
1984                 * this situation.  I choose: ide_error(...)
1985                 */
1986                return DRIVER(drive)->error(drive, "flagged_task_in_intr (unexpected data phase)", stat); 
1987        }
1988
1989        pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
1990        DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat);
1991
1992        taskfile_input_data(drive, pBuf, SECTOR_WORDS);
1993
1994        if (--rq->current_nr_sectors != 0) {
1995                /*
1996                 * (ks) We don't know which command was executed. 
1997                 * So, we wait the 'WORSTCASE' value.
1998                 */
1999                ide_set_handler(drive, &flagged_task_in_intr,  WAIT_WORSTCASE, NULL);
2000                return ide_started;
2001        }
2002        /*
2003         * (ks) Last sector was transfered, wait until drive is ready. 
2004         * This can take up to 10 usec. We willl wait max 50 us.
2005         */
2006        while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
2007                udelay(10);
2008        ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));
2009
2010        return ide_stopped;
2011}
2012
2013ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive)
2014{
2015        ide_hwif_t *hwif        = HWIF(drive);
2016        u8 stat                 = hwif->INB(IDE_STATUS_REG);
2017        struct request *rq      = HWGROUP(drive)->rq;
2018        char *pBuf              = NULL;
2019        int retries             = 5;
2020        unsigned int msect, nsect;
2021
2022        if (rq->current_nr_sectors == 0) 
2023                return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); 
2024
2025        msect = drive->mult_count;
2026        if (msect == 0) 
2027                return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); 
2028
2029        if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
2030                if (stat & ERR_STAT) {
2031                        return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat);
2032                }
2033                /*
2034                 * (ks) Unexpected ATA data phase detected.
2035                 * This should not happen. But, it can !
2036                 * I am not sure, which function is best to clean up
2037                 * this situation.  I choose: ide_error(...)
2038                 */
2039                return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); 
2040        }
2041
2042        nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
2043        pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
2044
2045        DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
2046            pBuf, nsect, rq->current_nr_sectors);
2047
2048        taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
2049
2050        rq->current_nr_sectors -= nsect;
2051        if (rq->current_nr_sectors != 0) {
2052                /*
2053                 * (ks) We don't know which command was executed. 
2054                 * So, we wait the 'WORSTCASE' value.
2055                 */
2056                ide_set_handler(drive, &flagged_task_mulin_intr,  WAIT_WORSTCASE, NULL);
2057                return ide_started;
2058        }
2059
2060        /*
2061         * (ks) Last sector was transfered, wait until drive is ready. 
2062         * This can take up to 10 usec. We willl wait max 50 us.
2063         */
2064        while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
2065                udelay(10);
2066        ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));
2067
2068        return ide_stopped;
2069}
2070
2071/*
2072 * Pre handler for command with PIO data-out phase
2073 */
2074ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq)
2075{
2076        ide_hwif_t *hwif        = HWIF(drive);
2077        u8 stat                 = hwif->INB(IDE_STATUS_REG);
2078        ide_startstop_t startstop;
2079
2080        if (!rq->current_nr_sectors) {
2081                return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat);
2082        }
2083
2084        if (ide_wait_stat(&startstop, drive, DATA_READY,
2085                        BAD_W_STAT, WAIT_DRQ)) {
2086                printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name);
2087                return startstop;
2088        }
2089
2090        taskfile_output_data(drive, rq->buffer, SECTOR_WORDS);
2091        --rq->current_nr_sectors;
2092
2093        return ide_started;
2094}
2095
2096ide_startstop_t flagged_task_out_intr (ide_drive_t *drive)
2097{
2098        ide_hwif_t *hwif        = HWIF(drive);
2099        u8 stat                 = hwif->INB(IDE_STATUS_REG);
2100        struct request *rq      = HWGROUP(drive)->rq;
2101        char *pBuf              = NULL;
2102
2103        if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) 
2104                return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat);
2105        
2106        if (!rq->current_nr_sectors) { 
2107                ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));
2108                return ide_stopped;
2109        }
2110
2111        if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) {
2112                /*
2113                 * (ks) Unexpected ATA data phase detected.
2114                 * This should not happen. But, it can !
2115                 * I am not sure, which function is best to clean up
2116                 * this situation.  I choose: ide_error(...)
2117                 */
2118                return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); 
2119        }
2120
2121        pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
2122        DTF("Write - rq->current_nr_sectors: %d, status: %02x\n",
2123                (int) rq->current_nr_sectors, stat);
2124
2125        taskfile_output_data(drive, pBuf, SECTOR_WORDS);
2126        --rq->current_nr_sectors;
2127
2128        /*
2129         * (ks) We don't know which command was executed. 
2130         * So, we wait the 'WORSTCASE' value.
2131         */
2132        ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL);
2133
2134        return ide_started;
2135}
2136
2137ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
2138{
2139        ide_hwif_t *hwif        = HWIF(drive);
2140        u8 stat                 = hwif->INB(IDE_STATUS_REG);
2141        char *pBuf              = NULL;
2142        ide_startstop_t startstop;
2143        unsigned int msect, nsect;
2144
2145        if (!rq->current_nr_sectors) 
2146                return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat);
2147
2148        msect = drive->mult_count;
2149        if (msect == 0)
2150                return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat);
2151
2152        if (ide_wait_stat(&startstop, drive, DATA_READY,
2153                        BAD_W_STAT, WAIT_DRQ)) {
2154                printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name);
2155                return startstop;
2156        }
2157
2158        nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
2159        pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
2160        DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
2161            pBuf, nsect, rq->current_nr_sectors);
2162
2163        taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
2164
2165        rq->current_nr_sectors -= nsect;
2166
2167        return ide_started;
2168}
2169
2170ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive)
2171{
2172        ide_hwif_t *hwif        = HWIF(drive);
2173        u8 stat                 = hwif->INB(IDE_STATUS_REG);
2174        struct request *rq      = HWGROUP(drive)->rq;
2175        char *pBuf              = NULL;
2176        unsigned int msect, nsect;
2177
2178        msect = drive->mult_count;
2179        if (msect == 0)
2180                return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat);
2181
2182        if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) 
2183                return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat);
2184        
2185        if (!rq->current_nr_sectors) { 
2186                ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));
2187                return ide_stopped;
2188        }
2189
2190        if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) {
2191                /*
2192                 * (ks) Unexpected ATA data phase detected.
2193                 * This should not happen. But, it can !
2194                 * I am not sure, which function is best to clean up
2195                 * this situation.  I choose: ide_error(...)
2196                 */
2197                return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); 
2198        }
2199
2200        nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
2201        pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
2202        DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
2203            pBuf, nsect, rq->current_nr_sectors);
2204
2205        taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
2206        rq->current_nr_sectors -= nsect;
2207
2208        /*
2209         * (ks) We don't know which command was executed. 
2210         * So, we wait the 'WORSTCASE' value.
2211         */
2212        ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL);
2213
2214        return ide_started;
2215}
2216
2217/*
2218 * Beginning of Taskfile OPCODE Library and feature sets.
2219 */
2220
2221#ifdef CONFIG_PKT_TASK_IOCTL
2222
2223int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2224{
2225#if 0
2226        switch(req_task->data_phase) {
2227                case TASKFILE_P_OUT_DMAQ:
2228                case TASKFILE_P_IN_DMAQ:
2229                case TASKFILE_P_OUT_DMA:
2230                case TASKFILE_P_IN_DMA:
2231                case TASKFILE_P_OUT:
2232                case TASKFILE_P_IN:
2233        }
2234#endif
2235        return -ENOMSG;
2236}
2237
2238EXPORT_SYMBOL(pkt_taskfile_ioctl);
2239
2240#endif /* CONFIG_PKT_TASK_IOCTL */
2241
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.