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.03  Feb 09, 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 #include "ide_modes.h"
  41 
  42 /*
  43  * This should be set to the system's local bus (PCI or VLB) speed,
  44  * e.g., 33 for a 486DX33 or 486DX2/66.  Legal values are anything
  45  * from 25 to 50.  Setting this too *low* will make the EIDE
  46  * controller unable to communicate with the disks.
  47  *
  48  * I suggest using a default of 50, since it should work ok with any
  49  * system.  (Low values cause problems because it multiplies by bus speed
  50  * to get cycles, and thus gets a too-small cycle count and tries to
  51  * access the disks too fast.  I tried this once under DOS and it locked
  52  * up the system.)      -- derekn@vw.ece.cmu.edu
  53  */
  54 #define ALI_14xx_BUS_SPEED      50      /* PCI / VLB bus speed */
  55 
  56 /* port addresses for auto-detection */
  57 #define ALI_NUM_PORTS 4
  58 static int ports[ALI_NUM_PORTS] = {0x074, 0x0f4, 0x034, 0x0e4};
  59 
  60 /* register initialization data */
  61 typedef struct { byte reg, data; } RegInitializer;
  62 
  63 static RegInitializer initData[] = {
  64         {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
  65         {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
  66         {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
  67         {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
  68         {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
  69         {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
  70         {0x35, 0x03}, {0x00, 0x00}
  71 };
  72 
  73 /* default timing parameters for each PIO mode */
  74 static struct { int time1, time2; } timeTab[4] = {
  75         {600, 165},     /* PIO 0 */
  76         {383, 125},     /* PIO 1 */
  77         {240, 100},     /* PIO 2 */
  78         {180,  80}      /* PIO 3 */
  79 };
  80 
  81 /* timing parameter registers for each drive */
  82 static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
  83         {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
  84         {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
  85         {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
  86         {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
  87 };
  88 
  89 static int basePort = 0;        /* base port address */
  90 static int regPort = 0;         /* port for register number */
  91 static int dataPort = 0;        /* port for register data */
  92 static byte regOn;      /* output to base port to access registers */
  93 static byte regOff;     /* output to base port to close registers */
  94 
  95 /*------------------------------------------------------------------------*/
  96 
  97 /*
  98  * Read a controller register.
  99  */
 100 static inline byte inReg (byte reg)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         outb_p(reg, regPort);
 103         return inb(dataPort);
 104 }
 105 
 106 /*
 107  * Write a controller register.
 108  */
 109 static void outReg (byte data, byte reg)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         outb_p(reg, regPort);
 112         outb_p(data, dataPort);
 113 }
 114 
 115 /*
 116  * Set PIO mode for the specified drive.
 117  * This function computes timing parameters
 118  * and sets controller registers accordingly.
 119  */
 120 static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         int driveNum;
 123         int time1, time2, time1a;
 124         byte param1, param2, param3, param4;
 125         struct hd_driveid *id = drive->id;
 126         unsigned long flags;
 127 
 128         if (pio == 255)
 129                 pio = ide_get_best_pio_mode(drive);
 130         if (pio > 3)
 131                 pio = 3;
 132 
 133         /* calculate timing, according to PIO mode */
 134         time1 = timeTab[pio].time1;
 135         time2 = timeTab[pio].time2;
 136         if (pio == 3) {
 137                 time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
 138                 if (time1a != 0 && time1a < time1)
 139                         time1 = time1a;
 140         }
 141         param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
 142         param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
 143         if (pio != 3) {
 144                 param3 += 8;
 145                 param4 += 8;
 146         }
 147         printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
 148                 drive->name, pio, time1, time2, param1, param2, param3, param4);
 149 
 150         /* stuff timing parameters into controller registers */
 151         driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
 152         save_flags(flags);
 153         cli();
 154         outb_p(regOn, basePort);
 155         outReg(param1, regTab[driveNum].reg1);
 156         outReg(param2, regTab[driveNum].reg2);
 157         outReg(param3, regTab[driveNum].reg3);
 158         outReg(param4, regTab[driveNum].reg4);
 159         outb_p(regOff, basePort);
 160         restore_flags(flags);
 161 }
 162 
 163 /*
 164  * Auto-detect the IDE controller port.
 165  */
 166 static int findPort (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         int i;
 169         byte t;
 170         unsigned long flags;
 171 
 172         save_flags(flags);
 173         cli();
 174         for (i = 0; i < ALI_NUM_PORTS; ++i) {
 175                 basePort = ports[i];
 176                 regOff = inb(basePort);
 177                 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
 178                         outb_p(regOn, basePort);
 179                         if (inb(basePort) == regOn) {
 180                                 regPort = basePort + 4;
 181                                 dataPort = basePort + 8;
 182                                 t = inReg(0) & 0xf0;
 183                                 outb_p(regOff, basePort);
 184                                 restore_flags(flags);
 185                                 if (t != 0x50)
 186                                         return 0;
 187                                 return 1;  /* success */
 188                         }
 189                 }
 190                 outb_p(regOff, basePort);
 191         }
 192         restore_flags(flags);
 193         return 0;
 194 }
 195 
 196 /*
 197  * Initialize controller registers with default values.
 198  */
 199 static int initRegisters (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 200         RegInitializer *p;
 201         byte t;
 202         unsigned long flags;
 203 
 204         save_flags(flags);
 205         cli();
 206         outb_p(regOn, basePort);
 207         for (p = initData; p->reg != 0; ++p)
 208                 outReg(p->data, p->reg);
 209         outb_p(0x01, regPort);
 210         t = inb(regPort) & 0x01;
 211         outb_p(regOff, basePort);
 212         restore_flags(flags);
 213         return t;
 214 }
 215 
 216 void init_ali14xx (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 217 {
 218         /* auto-detect IDE controller port */
 219         if (!findPort()) {
 220                 printk("ali14xx: not found\n");
 221                 return;
 222         }
 223 
 224         printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn);
 225         ide_hwifs[0].chipset = ide_ali14xx;
 226         ide_hwifs[1].chipset = ide_ali14xx;
 227         ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
 228         ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
 229 
 230         /* initialize controller registers */
 231         if (!initRegisters()) {
 232                 printk("ali14xx: Chip initialization failed\n");
 233                 return;
 234         }
 235 }

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