root/drivers/block/ali14xx.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. inReg
  2. outReg
  3. ali14xx_tune_drive
  4. findPort
  5. initRegisters
  6. init_ali14xx

   1 /*
   2  *  linux/drivers/block/ali14xx.c       Version 0.01  Feb 06, 1996
   3  *
   4  *  Copyright (C) 1996  Linus Torvalds & author (see below)
   5  */
   6 
   7 /*
   8  * ALI M14xx chipset EIDE controller
   9  *
  10  * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
  11  * Derek's notes follow:
  12  *
  13  * I think the code should be pretty understandable,
  14  * but I'll be happy to (try to) answer questions.
  15  *
  16  * The critical part is in the setupDrive function.  The initRegisters
  17  * function doesn't seem to be necessary, but the DOS driver does it, so
  18  * I threw it in.
  19  *
  20  * I've only tested this on my system, which only has one disk.  I posted
  21  * it to comp.sys.linux.hardware, so maybe some other people will try it
  22  * out.
  23  *
  24  * Derek Noonburg  (derekn@ece.cmu.edu)
  25  * 95-sep-26
  26  */
  27 
  28 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
  29 
  30 #include <linux/types.h>
  31 #include <linux/kernel.h>
  32 #include <linux/delay.h>
  33 #include <linux/timer.h>
  34 #include <linux/mm.h>
  35 #include <linux/ioport.h>
  36 #include <linux/blkdev.h>
  37 #include <linux/hdreg.h>
  38 #include <asm/io.h>
  39 #include "ide.h"
  40 
  41 #define ALI_14xx_BUS_SPEED      40      /* PCI / VLB bus speed */
  42 
  43 /* port addresses for auto-detection */
  44 #define ALI_NUM_PORTS 4
  45 static int ports[ALI_NUM_PORTS] = {0x074, 0x0f4, 0x034, 0x0e4};
  46 
  47 /* register initialization data */
  48 typedef struct { byte reg, data; } RegInitializer;
  49 
  50 static RegInitializer initData[] = {
  51         {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
  52         {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
  53         {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
  54         {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
  55         {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
  56         {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
  57         {0x35, 0x03}, {0x00, 0x00}
  58 };
  59 
  60 /* default timing parameters for each PIO mode */
  61 static struct { int time1, time2; } timeTab[4] = {
  62         {600, 165},     /* PIO 0 */
  63         {383, 125},     /* PIO 1 */
  64         {240, 100},     /* PIO 2 */
  65         {180,  80}      /* PIO 3 */
  66 };
  67 
  68 /* timing parameter registers for each drive */
  69 static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
  70         {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
  71         {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
  72         {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
  73         {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
  74 };
  75 
  76 static int basePort = 0;        /* base port address */
  77 static int regPort = 0;         /* port for register number */
  78 static int dataPort = 0;        /* port for register data */
  79 static byte regOn;      /* output to base port to access registers */
  80 static byte regOff;     /* output to base port to close registers */
  81 
  82 /*------------------------------------------------------------------------*/
  83 
  84 /*
  85  * Read a controller register.
  86  */
  87 static inline byte inReg (byte reg)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89         outb_p(reg, regPort);
  90         return inb(dataPort);
  91 }
  92 
  93 /*
  94  * Write a controller register.
  95  */
  96 static void outReg (byte data, byte reg)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         outb_p(reg, regPort);
  99         outb_p(data, dataPort);
 100 }
 101 
 102 /*
 103  * Set PIO mode for the specified drive.
 104  * This function computes timing parameters
 105  * and sets controller registers accordingly.
 106  */
 107 static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         int driveNum;
 110         int time1, time2, time1a;
 111         byte param1, param2, param3, param4;
 112         struct hd_driveid *id = drive->id;
 113         unsigned long flags;
 114 
 115         if (pio == 255)  {      /* auto-tune */
 116                 pio = id->tPIO;
 117                 if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01))
 118                         pio = 3;
 119         }
 120         /* calculate timing, according to PIO mode */
 121         time1 = timeTab[pio].time1;
 122         time2 = timeTab[pio].time2;
 123         if (pio == 3) {
 124                 time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
 125                 if (time1a != 0 && time1a < time1)
 126                         time1 = time1a;
 127         }
 128         param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
 129         param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
 130         if (pio != 3) {
 131                 param3 += 8;
 132                 param4 += 8;
 133         }
 134         printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
 135                 drive->name, pio, time1, time2, param1, param2, param3, param4);
 136 
 137         /* stuff timing parameters into controller registers */
 138         driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
 139         save_flags(flags);
 140         cli();
 141         outb_p(regOn, basePort);
 142         outReg(param1, regTab[driveNum].reg1);
 143         outReg(param2, regTab[driveNum].reg2);
 144         outReg(param3, regTab[driveNum].reg3);
 145         outReg(param4, regTab[driveNum].reg4);
 146         outb_p(regOff, basePort);
 147         restore_flags(flags);
 148 }
 149 
 150 /*
 151  * Auto-detect the IDE controller port.
 152  */
 153 static int findPort (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155         int i;
 156         byte t;
 157         unsigned long flags;
 158 
 159         save_flags(flags);
 160         cli();
 161         for (i = 0; i < ALI_NUM_PORTS; ++i) {
 162                 basePort = ports[i];
 163                 regOff = inb(basePort);
 164                 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
 165                         outb_p(regOn, basePort);
 166                         if (inb(basePort) == regOn) {
 167                                 regPort = basePort + 4;
 168                                 dataPort = basePort + 8;
 169                                 t = inReg(0) & 0xf0;
 170                                 outb_p(regOff, basePort);
 171                                 restore_flags(flags);
 172                                 if (t != 0x50)
 173                                         return 0;
 174                                 return 1;  /* success */
 175                         }
 176                 }
 177                 outb_p(regOff, basePort);
 178         }
 179         restore_flags(flags);
 180         return 0;
 181 }
 182 
 183 /*
 184  * Initialize controller registers with default values.
 185  */
 186 static int initRegisters (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 187         RegInitializer *p;
 188         byte t;
 189         unsigned long flags;
 190 
 191         save_flags(flags);
 192         cli();
 193         outb_p(regOn, basePort);
 194         for (p = initData; p->reg != 0; ++p)
 195                 outReg(p->data, p->reg);
 196         outb_p(0x01, regPort);
 197         t = inb(regPort) & 0x01;
 198         outb_p(regOff, basePort);
 199         restore_flags(flags);
 200         return t;
 201 }
 202 
 203 void init_ali14xx (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205         /* auto-detect IDE controller port */
 206         if (!findPort()) {
 207                 printk("ali14xx: not found\n");
 208                 return;
 209         }
 210 
 211         printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn);
 212         ide_hwifs[0].chipset = ide_ali14xx;
 213         ide_hwifs[1].chipset = ide_ali14xx;
 214         ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
 215         ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
 216 
 217         /* initialize controller registers */
 218         if (!initRegisters()) {
 219                 printk("ali14xx: Chip initialization failed\n");
 220                 return;
 221         }
 222 }

/* [previous][next][first][last][top][bottom][index][help] */