~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/ide/ali14xx.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/ide/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  * Works for ALI M1439/1443/1445/1487/1489 chipsets.
 11  *
 12  * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
 13  * Derek's notes follow:
 14  *
 15  * I think the code should be pretty understandable,
 16  * but I'll be happy to (try to) answer questions.
 17  *
 18  * The critical part is in the setupDrive function.  The initRegisters
 19  * function doesn't seem to be necessary, but the DOS driver does it, so
 20  * I threw it in.
 21  *
 22  * I've only tested this on my system, which only has one disk.  I posted
 23  * it to comp.sys.linux.hardware, so maybe some other people will try it
 24  * out.
 25  *
 26  * Derek Noonburg  (derekn@ece.cmu.edu)
 27  * 95-sep-26
 28  *
 29  * Update 96-jul-13:
 30  *
 31  * I've since upgraded to two disks and a CD-ROM, with no trouble, and
 32  * I've also heard from several others who have used it successfully.
 33  * This driver appears to work with both the 1443/1445 and the 1487/1489
 34  * chipsets.  I've added support for PIO mode 4 for the 1487.  This
 35  * seems to work just fine on the 1443 also, although I'm not sure it's
 36  * advertised as supporting mode 4.  (I've been running a WDC AC21200 in
 37  * mode 4 for a while now with no trouble.)  -Derek
 38  */
 39 
 40 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
 41 
 42 #include <linux/types.h>
 43 #include <linux/kernel.h>
 44 #include <linux/delay.h>
 45 #include <linux/timer.h>
 46 #include <linux/mm.h>
 47 #include <linux/ioport.h>
 48 #include <linux/blkdev.h>
 49 #include <linux/hdreg.h>
 50 #include <linux/ide.h>
 51 #include <linux/init.h>
 52 
 53 #include <asm/io.h>
 54 
 55 #include "ide_modes.h"
 56 
 57 /* port addresses for auto-detection */
 58 #define ALI_NUM_PORTS 4
 59 static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
 60 
 61 /* register initialization data */
 62 typedef struct { byte reg, data; } RegInitializer;
 63 
 64 static RegInitializer initData[] __initdata = {
 65         {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
 66         {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
 67         {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
 68         {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
 69         {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
 70         {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
 71         {0x35, 0x03}, {0x00, 0x00}
 72 };
 73 
 74 #define ALI_MAX_PIO 4
 75 
 76 /* timing parameter registers for each drive */
 77 static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
 78         {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
 79         {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
 80         {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
 81         {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
 82 };
 83 
 84 static int basePort = 0;        /* base port address */
 85 static int regPort = 0;         /* port for register number */
 86 static int dataPort = 0;        /* port for register data */
 87 static byte regOn;      /* output to base port to access registers */
 88 static byte regOff;     /* output to base port to close registers */
 89 
 90 /*------------------------------------------------------------------------*/
 91 
 92 /*
 93  * Read a controller register.
 94  */
 95 static inline byte inReg (byte reg)
 96 {
 97         outb_p(reg, regPort);
 98         return inb(dataPort);
 99 }
100 
101 /*
102  * Write a controller register.
103  */
104 static void outReg (byte data, byte reg)
105 {
106         outb_p(reg, regPort);
107         outb_p(data, dataPort);
108 }
109 
110 /*
111  * Set PIO mode for the specified drive.
112  * This function computes timing parameters
113  * and sets controller registers accordingly.
114  */
115 static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
116 {
117         int driveNum;
118         int time1, time2;
119         byte param1, param2, param3, param4;
120         unsigned long flags;
121         ide_pio_data_t d;
122         int bus_speed = system_bus_clock();
123 
124         pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
125 
126         /* calculate timing, according to PIO mode */
127         time1 = d.cycle_time;
128         time2 = ide_pio_timings[pio].active_time;
129         param3 = param1 = (time2 * bus_speed + 999) / 1000;
130         param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
131         if (pio < 3) {
132                 param3 += 8;
133                 param4 += 8;
134         }
135         printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
136                 drive->name, pio, time1, time2, param1, param2, param3, param4);
137 
138         /* stuff timing parameters into controller registers */
139         driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
140         save_flags(flags);      /* all CPUs */
141         cli();                  /* all CPUs */
142         outb_p(regOn, basePort);
143         outReg(param1, regTab[driveNum].reg1);
144         outReg(param2, regTab[driveNum].reg2);
145         outReg(param3, regTab[driveNum].reg3);
146         outReg(param4, regTab[driveNum].reg4);
147         outb_p(regOff, basePort);
148         restore_flags(flags);   /* all CPUs */
149 }
150 
151 /*
152  * Auto-detect the IDE controller port.
153  */
154 static int __init findPort (void)
155 {
156         int i;
157         byte t;
158         unsigned long flags;
159 
160         __save_flags(flags);    /* local CPU only */
161         __cli();                /* local CPU only */
162         for (i = 0; i < ALI_NUM_PORTS; ++i) {
163                 basePort = ports[i];
164                 regOff = inb(basePort);
165                 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
166                         outb_p(regOn, basePort);
167                         if (inb(basePort) == regOn) {
168                                 regPort = basePort + 4;
169                                 dataPort = basePort + 8;
170                                 t = inReg(0) & 0xf0;
171                                 outb_p(regOff, basePort);
172                                 __restore_flags(flags); /* local CPU only */
173                                 if (t != 0x50)
174                                         return 0;
175                                 return 1;  /* success */
176                         }
177                 }
178                 outb_p(regOff, basePort);
179         }
180         __restore_flags(flags); /* local CPU only */
181         return 0;
182 }
183 
184 /*
185  * Initialize controller registers with default values.
186  */
187 static int __init initRegisters (void) {
188         RegInitializer *p;
189         byte t;
190         unsigned long flags;
191 
192         __save_flags(flags);    /* local CPU only */
193         __cli();                /* local CPU only */
194         outb_p(regOn, basePort);
195         for (p = initData; p->reg != 0; ++p)
196                 outReg(p->data, p->reg);
197         outb_p(0x01, regPort);
198         t = inb(regPort) & 0x01;
199         outb_p(regOff, basePort);
200         __restore_flags(flags); /* local CPU only */
201         return t;
202 }
203 
204 void __init init_ali14xx (void)
205 {
206         /* auto-detect IDE controller port */
207         if (!findPort()) {
208                 printk("\nali14xx: not found");
209                 return;
210         }
211 
212         printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn);
213         ide_hwifs[0].chipset = ide_ali14xx;
214         ide_hwifs[1].chipset = ide_ali14xx;
215         ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
216         ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
217         ide_hwifs[0].mate = &ide_hwifs[1];
218         ide_hwifs[1].mate = &ide_hwifs[0];
219         ide_hwifs[1].channel = 1;
220 
221         /* initialize controller registers */
222         if (!initRegisters()) {
223                 printk("\nali14xx: Chip initialization failed");
224                 return;
225         }
226 }
227 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.