ali14xx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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