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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/ide/umc8672.c Version 0.05 Jul 31, 1996
  3.  *
  4.  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  5.  */
  6. /*
  7.  *  Principal Author/Maintainer:  PODIEN@hml2.atlas.de (Wolfram Podien)
  8.  *
  9.  *  This file provides support for the advanced features
  10.  *  of the UMC 8672 IDE interface.
  11.  *
  12.  *  Version 0.01 Initial version, hacked out of ide.c,
  13.  * and #include'd rather than compiled separately.
  14.  * This will get cleaned up in a subsequent release.
  15.  *
  16.  *  Version 0.02 now configs/compiles separate from ide.c  -ml
  17.  *  Version 0.03 enhanced auto-tune, fix display bug
  18.  *  Version 0.05 replace sti() with restore_flags()  -ml
  19.  * add detection of possible race condition  -ml
  20.  */
  21. /*
  22.  * VLB Controller Support from 
  23.  * Wolfram Podien
  24.  * Rohoefe 3
  25.  * D28832 Achim
  26.  * Germany
  27.  *
  28.  * To enable UMC8672 support there must a lilo line like
  29.  * append="ide0=umc8672"...
  30.  * To set the speed according to the abilities of the hardware there must be a
  31.  * line like
  32.  * #define UMC_DRIVE0 11
  33.  * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
  34.  * are some lines present). 0 - 11 are allowed speed values. These values are
  35.  * the results from the DOS speed test program supplied from UMC. 11 is the 
  36.  * highest speed (about PIO mode 3)
  37.  */
  38. #define REALLY_SLOW_IO /* some 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. /*
  52.  * Default speeds.  These can be changed with "auto-tune" and/or hdparm.
  53.  */
  54. #define UMC_DRIVE0      1              /* DOS measured drive speeds */
  55. #define UMC_DRIVE1      1              /* 0 to 11 allowed */
  56. #define UMC_DRIVE2      1              /* 11 = Fastest Speed */
  57. #define UMC_DRIVE3      1              /* In case of crash reduce speed */
  58. static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
  59. static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
  60. /*       0    1    2    3    4    5    6    7    8    9    10   11      */
  61. static const byte speedtab [3][12] = {
  62. {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
  63. {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
  64. {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
  65. static void out_umc (char port,char wert)
  66. {
  67. outb_p (port,0x108);
  68. outb_p (wert,0x109);
  69. }
  70. static inline byte in_umc (char port)
  71. {
  72. outb_p (port,0x108);
  73. return inb_p (0x109);
  74. }
  75. static void umc_set_speeds (byte speeds[])
  76. {
  77. int i, tmp;
  78. outb_p (0x5A,0x108); /* enable umc */
  79. out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
  80. out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
  81. tmp = 0;
  82. for (i = 3; i >= 0; i--)
  83. {
  84. tmp = (tmp << 2) | speedtab[1][speeds[i]];
  85. }
  86. out_umc (0xdc,tmp);
  87. for (i = 0;i < 4; i++)
  88. {
  89. out_umc (0xd0+i,speedtab[2][speeds[i]]);
  90. out_umc (0xd8+i,speedtab[2][speeds[i]]);
  91. }
  92. outb_p (0xa5,0x108); /* disable umc */
  93. printk ("umc8672: drive speeds [0 to 11]: %d %d %d %dn",
  94. speeds[0], speeds[1], speeds[2], speeds[3]);
  95. }
  96. static void tune_umc (ide_drive_t *drive, byte pio)
  97. {
  98. unsigned long flags;
  99. ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
  100. pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
  101. printk("%s: setting umc8672 to PIO mode%d (speed %d)n", drive->name, pio, pio_to_umc[pio]);
  102. save_flags(flags); /* all CPUs */
  103. cli(); /* all CPUs */
  104. if (hwgroup && hwgroup->handler != NULL) {
  105. printk("umc8672: other interface is busy: exiting tune_umc()n");
  106. } else {
  107. current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
  108. umc_set_speeds (current_speeds);
  109. }
  110. restore_flags(flags); /* all CPUs */
  111. }
  112. void __init init_umc8672 (void) /* called from ide.c */
  113. {
  114. unsigned long flags;
  115. __save_flags(flags); /* local CPU only */
  116. __cli(); /* local CPU only */
  117. if (check_region(0x108, 2)) {
  118. __restore_flags(flags);
  119. printk("numc8672: PORTS 0x108-0x109 ALREADY IN USEn");
  120. return;
  121. }
  122. outb_p (0x5A,0x108); /* enable umc */
  123. if (in_umc (0xd5) != 0xa0)
  124. {
  125. __restore_flags(flags); /* local CPU only */
  126. printk ("umc8672: not foundn");
  127. return;  
  128. }
  129. outb_p (0xa5,0x108); /* disable umc */
  130. umc_set_speeds (current_speeds);
  131. __restore_flags(flags); /* local CPU only */
  132. request_region(0x108, 2, "umc8672");
  133. ide_hwifs[0].chipset = ide_umc8672;
  134. ide_hwifs[1].chipset = ide_umc8672;
  135. ide_hwifs[0].tuneproc = &tune_umc;
  136. ide_hwifs[1].tuneproc = &tune_umc;
  137. ide_hwifs[0].mate = &ide_hwifs[1];
  138. ide_hwifs[1].mate = &ide_hwifs[0];
  139. ide_hwifs[1].channel = 1;
  140. }