ht6560b.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/ide/ht6560b.c Version 0.07 Feb  1, 2000
  3.  *
  4.  *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
  5.  */
  6. /*
  7.  *
  8.  *  Version 0.01        Initial version hacked out of ide.c
  9.  *
  10.  *  Version 0.02        Added support for PIO modes, auto-tune
  11.  *
  12.  *  Version 0.03        Some cleanups
  13.  *
  14.  *  Version 0.05        PIO mode cycle timings auto-tune using bus-speed
  15.  *
  16.  *  Version 0.06        Prefetch mode now defaults no OFF. To set
  17.  *                      prefetch mode OFF/ON use "hdparm -p8/-p9".
  18.  *                      Unmask irq is disabled when prefetch mode
  19.  *                      is enabled.
  20.  *
  21.  *  Version 0.07        Trying to fix CD-ROM detection problem.
  22.  *                      "Prefetch" mode bit OFF for ide disks and
  23.  *                      ON for anything else.
  24.  *
  25.  *
  26.  *  HT-6560B EIDE-controller support
  27.  *  To activate controller support use kernel parameter "ide0=ht6560b".
  28.  *  Use hdparm utility to enable PIO mode support.
  29.  *
  30.  *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
  31.  *             Jan Evert van Grootheest   <janevert@iae.nl>
  32.  *
  33.  *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
  34.  */
  35. #define HT6560B_VERSION "v0.07"
  36. #undef REALLY_SLOW_IO /* most systems can safely undef this */
  37. #include <linux/types.h>
  38. #include <linux/kernel.h>
  39. #include <linux/delay.h>
  40. #include <linux/timer.h>
  41. #include <linux/mm.h>
  42. #include <linux/ioport.h>
  43. #include <linux/blkdev.h>
  44. #include <linux/hdreg.h>
  45. #include <linux/ide.h>
  46. #include <linux/init.h>
  47. #include <asm/io.h>
  48. #include "ide_modes.h"
  49. /* #define DEBUG */  /* remove comments for DEBUG messages */
  50. /*
  51.  * The special i/o-port that HT-6560B uses to configuration:
  52.  *    bit0 (0x01): "1" selects secondary interface
  53.  *    bit2 (0x04): "1" enables FIFO function
  54.  *    bit5 (0x20): "1" enables prefetched data read function  (???)
  55.  *
  56.  * The special i/o-port that HT-6560A uses to configuration:
  57.  *    bit0 (0x01): "1" selects secondary interface
  58.  *    bit1 (0x02): "1" enables prefetched data read function
  59.  *    bit2 (0x04): "0" enables multi-master system       (?)
  60.  *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time       (?)
  61.  */
  62. #define HT_CONFIG_PORT   0x3e6
  63. #define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8)
  64. /*
  65.  * FIFO + PREFETCH (both a/b-model)
  66.  */
  67. #define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
  68. /* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
  69. #define HT_SECONDARY_IF   0x01
  70. #define HT_PREFETCH_MODE  0x20
  71. /*
  72.  * ht6560b Timing values:
  73.  *
  74.  * I reviewed some assembler source listings of htide drivers and found
  75.  * out how they setup those cycle time interfacing values, as they at Holtek
  76.  * call them. IDESETUP.COM that is supplied with the drivers figures out
  77.  * optimal values and fetches those values to drivers. I found out that
  78.  * they use IDE_SELECT_REG to fetch timings to the ide board right after
  79.  * interface switching. After that it was quite easy to add code to
  80.  * ht6560b.c.
  81.  *
  82.  * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
  83.  * for hda and hdc. But hdb needed higher values to work, so I guess
  84.  * that sometimes it is necessary to give higher value than IDESETUP
  85.  * gives.   [see cmd640.c for an extreme example of this. -ml]
  86.  *
  87.  * Perhaps I should explain something about these timing values:
  88.  * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
  89.  * of the value is the Active Time  (at). Minimum value 2 is the fastest and
  90.  * the maximum value 15 is the slowest. Default values should be 15 for both.
  91.  * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
  92.  * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
  93.  * similar. If value is too small there will be all sorts of failures.
  94.  *
  95.  * Timing byte consists of
  96.  * High nibble:  Recovery Cycle Time  (rt)
  97.  *      The valid values range from 2 to 15. The default is 15.
  98.  *
  99.  * Low nibble:   Active Cycle Time    (at)
  100.  *      The valid values range from 2 to 15. The default is 15.
  101.  *
  102.  * You can obtain optimized timing values by running Holtek IDESETUP.COM
  103.  * for DOS. DOS drivers get their timing values from command line, where
  104.  * the first value is the Recovery Time and the second value is the
  105.  * Active Time for each drive. Smaller value gives higher speed.
  106.  * In case of failures you should probably fall back to a higher value.
  107.  */
  108. #define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff)
  109. #define HT_TIMING_DEFAULT 0xff
  110. /*
  111.  * This routine handles interface switching for the peculiar hardware design
  112.  * on the F.G.I./Holtek HT-6560B VLB IDE interface.
  113.  * The HT-6560B can only enable one IDE port at a time, and requires a
  114.  * silly sequence (below) whenever we switch between primary and secondary.
  115.  */
  116. /*
  117.  * This routine is invoked from ide.c to prepare for access to a given drive.
  118.  */
  119. static void ht6560b_selectproc (ide_drive_t *drive)
  120. {
  121. unsigned long flags;
  122. static byte current_select = 0;
  123. static byte current_timing = 0;
  124. byte select, timing;
  125. __save_flags (flags); /* local CPU only */
  126. __cli(); /* local CPU only */
  127. select = HT_CONFIG(drive);
  128. timing = HT_TIMING(drive);
  129. if (select != current_select || timing != current_timing) {
  130. current_select = select;
  131. current_timing = timing;
  132. if (drive->media != ide_disk || !drive->present)
  133. select |= HT_PREFETCH_MODE;
  134. (void) inb(HT_CONFIG_PORT);
  135. (void) inb(HT_CONFIG_PORT);
  136. (void) inb(HT_CONFIG_PORT);
  137. (void) inb(HT_CONFIG_PORT);
  138. outb(select, HT_CONFIG_PORT);
  139. /*
  140.  * Set timing for this drive:
  141.  */
  142. outb(timing, IDE_SELECT_REG);
  143. (void) inb(IDE_STATUS_REG);
  144. #ifdef DEBUG
  145. printk("ht6560b: %s: select=%#x timing=%#xn", drive->name, select, timing);
  146. #endif
  147. }
  148. __restore_flags (flags); /* local CPU only */
  149. }
  150. /*
  151.  * Autodetection and initialization of ht6560b
  152.  */
  153. static int __init try_to_init_ht6560b(void)
  154. {
  155. byte orig_value;
  156. int i;
  157. /* Autodetect ht6560b */
  158. if ((orig_value=inb(HT_CONFIG_PORT)) == 0xff)
  159. return 0;
  160. for (i=3;i>0;i--) {
  161. outb(0x00, HT_CONFIG_PORT);
  162. if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
  163. outb(orig_value, HT_CONFIG_PORT);
  164. return 0;
  165. }
  166. }
  167. outb(0x00, HT_CONFIG_PORT);
  168. if ((~inb(HT_CONFIG_PORT))& 0x3f) {
  169. outb(orig_value, HT_CONFIG_PORT);
  170. return 0;
  171. }
  172. /*
  173.  * Ht6560b autodetected
  174.  */
  175. outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
  176. outb(HT_TIMING_DEFAULT, 0x1f6);  /* IDE_SELECT_REG */
  177. (void) inb(0x1f7);               /* IDE_STATUS_REG */
  178. printk("nht6560b " HT6560B_VERSION
  179.        ": chipset detected and initialized"
  180. #ifdef DEBUG
  181.        " with debug enabled"
  182. #endif
  183. );
  184. return 1;
  185. }
  186. static byte ht_pio2timings(ide_drive_t *drive, byte pio)
  187. {
  188. int active_time, recovery_time;
  189. int active_cycles, recovery_cycles;
  190. ide_pio_data_t d;
  191. int bus_speed = system_bus_clock();
  192.         if (pio) {
  193. pio = ide_get_best_pio_mode(drive, pio, 5, &d);
  194. /*
  195.  *  Just like opti621.c we try to calculate the
  196.  *  actual cycle time for recovery and activity
  197.  *  according system bus speed.
  198.  */
  199. active_time = ide_pio_timings[pio].active_time;
  200. recovery_time = d.cycle_time 
  201. - active_time
  202. - ide_pio_timings[pio].setup_time;
  203. /*
  204.  *  Cycle times should be Vesa bus cycles
  205.  */
  206. active_cycles   = (active_time   * bus_speed + 999) / 1000;
  207. recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
  208. /*
  209.  *  Upper and lower limits
  210.  */
  211. if (active_cycles   < 2)  active_cycles   = 2;
  212. if (recovery_cycles < 2)  recovery_cycles = 2;
  213. if (active_cycles   > 15) active_cycles   = 15;
  214. if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
  215. #ifdef DEBUG
  216. printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
  217. #endif
  218. return (byte)((recovery_cycles << 4) | active_cycles);
  219. } else {
  220. #ifdef DEBUG
  221. printk("ht6560b: drive %s setting pio=0n", drive->name);
  222. #endif
  223. return HT_TIMING_DEFAULT;    /* default setting */
  224. }
  225. }
  226. /*
  227.  *  Enable/Disable so called prefetch mode
  228.  */
  229. static void ht_set_prefetch(ide_drive_t *drive, byte state)
  230. {
  231. unsigned long flags;
  232. int t = HT_PREFETCH_MODE << 8;
  233. save_flags (flags); /* all CPUs */
  234. cli();         /* all CPUs */
  235. /*
  236.  *  Prefetch mode and unmask irq seems to conflict
  237.  */
  238. if (state) {
  239. drive->drive_data |= t;   /* enable prefetch mode */
  240. drive->no_unmask = 1;
  241. drive->unmask = 0;
  242. } else {
  243. drive->drive_data &= ~t;  /* disable prefetch mode */
  244. drive->no_unmask = 0;
  245. }
  246. restore_flags (flags); /* all CPUs */
  247. #ifdef DEBUG
  248. printk("ht6560b: drive %s prefetch mode %sabledn", drive->name, (state ? "en" : "dis"));
  249. #endif
  250. }
  251. static void tune_ht6560b (ide_drive_t *drive, byte pio)
  252. {
  253. unsigned long flags;
  254. byte timing;
  255. switch (pio) {
  256. case 8:         /* set prefetch off */
  257. case 9:         /* set prefetch on */
  258. ht_set_prefetch(drive, pio & 1);
  259. return;
  260. }
  261. timing = ht_pio2timings(drive, pio);
  262. save_flags (flags); /* all CPUs */
  263. cli();         /* all CPUs */
  264. drive->drive_data &= 0xff00;
  265. drive->drive_data |= timing;
  266. restore_flags (flags); /* all CPUs */
  267. #ifdef DEBUG
  268. printk("ht6560b: drive %s tuned to pio mode %#x timing=%#xn", drive->name, pio, timing);
  269. #endif
  270. }
  271. void __init init_ht6560b (void)
  272. {
  273. int t;
  274. if (check_region(HT_CONFIG_PORT,1)) {
  275. printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USEn", HT_CONFIG_PORT);
  276. } else {
  277. if (try_to_init_ht6560b()) {
  278. request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name);
  279. ide_hwifs[0].chipset = ide_ht6560b;
  280. ide_hwifs[1].chipset = ide_ht6560b;
  281. ide_hwifs[0].selectproc = &ht6560b_selectproc;
  282. ide_hwifs[1].selectproc = &ht6560b_selectproc;
  283. ide_hwifs[0].tuneproc = &tune_ht6560b;
  284. ide_hwifs[1].tuneproc = &tune_ht6560b;
  285. ide_hwifs[0].serialized = 1;  /* is this needed? */
  286. ide_hwifs[1].serialized = 1;  /* is this needed? */
  287. ide_hwifs[0].mate = &ide_hwifs[1];
  288. ide_hwifs[1].mate = &ide_hwifs[0];
  289. ide_hwifs[1].channel = 1;
  290. /*
  291.  * Setting default configurations for drives
  292.  */
  293. t = (HT_CONFIG_DEFAULT << 8);
  294. t |= HT_TIMING_DEFAULT;
  295. ide_hwifs[0].drives[0].drive_data = t;
  296. ide_hwifs[0].drives[1].drive_data = t;
  297. t |= (HT_SECONDARY_IF << 8);
  298. ide_hwifs[1].drives[0].drive_data = t;
  299. ide_hwifs[1].drives[1].drive_data = t;
  300. } else
  301. printk(KERN_ERR "ht6560b: not foundn");
  302. }
  303. }