linux/drivers/ide/ide-timing.h
<<
>>
Prefs
   1#ifndef _IDE_TIMING_H
   2#define _IDE_TIMING_H
   3
   4/*
   5 * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
   6 *
   7 *  Copyright (c) 1999-2001 Vojtech Pavlik
   8 */
   9
  10/*
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24 *
  25 * Should you need to contact me, the author, you can do so either by
  26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  28 */
  29
  30#include <linux/kernel.h>
  31#include <linux/hdreg.h>
  32
  33#define XFER_PIO_5              0x0d
  34#define XFER_UDMA_SLOW          0x4f
  35
  36struct ide_timing {
  37        short mode;
  38        short setup;    /* t1 */
  39        short act8b;    /* t2 for 8-bit io */
  40        short rec8b;    /* t2i for 8-bit io */
  41        short cyc8b;    /* t0 for 8-bit io */
  42        short active;   /* t2 or tD */
  43        short recover;  /* t2i or tK */
  44        short cycle;    /* t0 */
  45        short udma;     /* t2CYCTYP/2 */
  46};
  47
  48/*
  49 * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
  50 * These were taken from ATA/ATAPI-6 standard, rev 0a, except
  51 * for PIO 5, which is a nonstandard extension and UDMA6, which
  52 * is currently supported only by Maxtor drives. 
  53 */
  54
  55static struct ide_timing ide_timing[] = {
  56
  57        { XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
  58        { XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
  59        { XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
  60        { XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
  61
  62        { XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
  63        { XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
  64        { XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
  65
  66        { XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 },
  67                                          
  68        { XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
  69        { XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
  70        { XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
  71                                          
  72        { XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
  73        { XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
  74        { XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
  75
  76        { XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 },
  77        { XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
  78        { XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
  79
  80        { XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
  81        { XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
  82        { XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
  83
  84        { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 },
  85
  86        { -1 }
  87};
  88
  89#define IDE_TIMING_SETUP        0x01
  90#define IDE_TIMING_ACT8B        0x02
  91#define IDE_TIMING_REC8B        0x04
  92#define IDE_TIMING_CYC8B        0x08
  93#define IDE_TIMING_8BIT         0x0e
  94#define IDE_TIMING_ACTIVE       0x10
  95#define IDE_TIMING_RECOVER      0x20
  96#define IDE_TIMING_CYCLE        0x40
  97#define IDE_TIMING_UDMA         0x80
  98#define IDE_TIMING_ALL          0xff
  99
 100#define FIT(v,vmin,vmax)        max_t(short,min_t(short,v,vmax),vmin)
 101#define ENOUGH(v,unit)          (((v)-1)/(unit)+1)
 102#define EZ(v,unit)              ((v)?ENOUGH(v,unit):0)
 103
 104#define XFER_MODE       0xf0
 105#define XFER_MWDMA      0x20
 106#define XFER_EPIO       0x01
 107#define XFER_PIO        0x00
 108
 109static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
 110{
 111        q->setup   = EZ(t->setup   * 1000,  T);
 112        q->act8b   = EZ(t->act8b   * 1000,  T);
 113        q->rec8b   = EZ(t->rec8b   * 1000,  T);
 114        q->cyc8b   = EZ(t->cyc8b   * 1000,  T);
 115        q->active  = EZ(t->active  * 1000,  T);
 116        q->recover = EZ(t->recover * 1000,  T);
 117        q->cycle   = EZ(t->cycle   * 1000,  T);
 118        q->udma    = EZ(t->udma    * 1000, UT);
 119}
 120
 121static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
 122{
 123        if (what & IDE_TIMING_SETUP  ) m->setup   = max(a->setup,   b->setup);
 124        if (what & IDE_TIMING_ACT8B  ) m->act8b   = max(a->act8b,   b->act8b);
 125        if (what & IDE_TIMING_REC8B  ) m->rec8b   = max(a->rec8b,   b->rec8b);
 126        if (what & IDE_TIMING_CYC8B  ) m->cyc8b   = max(a->cyc8b,   b->cyc8b);
 127        if (what & IDE_TIMING_ACTIVE ) m->active  = max(a->active,  b->active);
 128        if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
 129        if (what & IDE_TIMING_CYCLE  ) m->cycle   = max(a->cycle,   b->cycle);
 130        if (what & IDE_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
 131}
 132
 133static struct ide_timing* ide_timing_find_mode(short speed)
 134{
 135        struct ide_timing *t;
 136
 137        for (t = ide_timing; t->mode != speed; t++)
 138                if (t->mode < 0)
 139                        return NULL;
 140        return t; 
 141}
 142
 143static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing *t, int T, int UT)
 144{
 145        struct hd_driveid *id = drive->id;
 146        struct ide_timing *s, p;
 147
 148/*
 149 * Find the mode.
 150 */
 151
 152        if (!(s = ide_timing_find_mode(speed)))
 153                return -EINVAL;
 154
 155/*
 156 * Copy the timing from the table.
 157 */
 158
 159        *t = *s;
 160
 161/*
 162 * If the drive is an EIDE drive, it can tell us it needs extended
 163 * PIO/MWDMA cycle timing.
 164 */
 165
 166        if (id && id->field_valid & 2) {        /* EIDE drive */
 167
 168                memset(&p, 0, sizeof(p));
 169
 170                switch (speed & XFER_MODE) {
 171
 172                        case XFER_PIO:
 173                                if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio;
 174                                                    else p.cycle = p.cyc8b = id->eide_pio_iordy;
 175                                break;
 176
 177                        case XFER_MWDMA:
 178                                p.cycle = id->eide_dma_min;
 179                                break;
 180                }
 181
 182                ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
 183        }
 184
 185/*
 186 * Convert the timing to bus clock counts.
 187 */
 188
 189        ide_timing_quantize(t, t, T, UT);
 190
 191/*
 192 * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
 193 * and some other commands. We have to ensure that the DMA cycle timing is
 194 * slower/equal than the fastest PIO timing.
 195 */
 196
 197        if ((speed & XFER_MODE) != XFER_PIO) {
 198                u8 pio = ide_get_best_pio_mode(drive, 255, 5);
 199                ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT);
 200                ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
 201        }
 202
 203/*
 204 * Lenghten active & recovery time so that cycle time is correct.
 205 */
 206
 207        if (t->act8b + t->rec8b < t->cyc8b) {
 208                t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
 209                t->rec8b = t->cyc8b - t->act8b;
 210        }
 211
 212        if (t->active + t->recover < t->cycle) {
 213                t->active += (t->cycle - (t->active + t->recover)) / 2;
 214                t->recover = t->cycle - t->active;
 215        }
 216
 217        return 0;
 218}
 219
 220#endif
 221
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.