Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #include <linux/init.h>
  2 #include <linux/mm.h>
  3 #include <asm/mtrr.h>
  4 #include <asm/msr.h>
  5 #include <asm/io.h>
  6 #include <asm/processor-cyrix.h>
  7 #include <asm/processor-flags.h>
  8 #include "mtrr.h"
  9 
 10 static void
 11 cyrix_get_arr(unsigned int reg, unsigned long *base,
 12               unsigned long *size, mtrr_type * type)
 13 {
 14         unsigned long flags;
 15         unsigned char arr, ccr3, rcr, shift;
 16 
 17         arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
 18 
 19         /* Save flags and disable interrupts */
 20         local_irq_save(flags);
 21 
 22         ccr3 = getCx86(CX86_CCR3);
 23         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN */
 24         ((unsigned char *) base)[3] = getCx86(arr);
 25         ((unsigned char *) base)[2] = getCx86(arr + 1);
 26         ((unsigned char *) base)[1] = getCx86(arr + 2);
 27         rcr = getCx86(CX86_RCR_BASE + reg);
 28         setCx86(CX86_CCR3, ccr3);       /* disable MAPEN */
 29 
 30         /* Enable interrupts if it was enabled previously */
 31         local_irq_restore(flags);
 32         shift = ((unsigned char *) base)[1] & 0x0f;
 33         *base >>= PAGE_SHIFT;
 34 
 35         /* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7
 36          * Note: shift==0xf means 4G, this is unsupported.
 37          */
 38         if (shift)
 39                 *size = (reg < 7 ? 0x1UL : 0x40UL) << (shift - 1);
 40         else
 41                 *size = 0;
 42 
 43         /* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */
 44         if (reg < 7) {
 45                 switch (rcr) {
 46                 case 1:
 47                         *type = MTRR_TYPE_UNCACHABLE;
 48                         break;
 49                 case 8:
 50                         *type = MTRR_TYPE_WRBACK;
 51                         break;
 52                 case 9:
 53                         *type = MTRR_TYPE_WRCOMB;
 54                         break;
 55                 case 24:
 56                 default:
 57                         *type = MTRR_TYPE_WRTHROUGH;
 58                         break;
 59                 }
 60         } else {
 61                 switch (rcr) {
 62                 case 0:
 63                         *type = MTRR_TYPE_UNCACHABLE;
 64                         break;
 65                 case 8:
 66                         *type = MTRR_TYPE_WRCOMB;
 67                         break;
 68                 case 9:
 69                         *type = MTRR_TYPE_WRBACK;
 70                         break;
 71                 case 25:
 72                 default:
 73                         *type = MTRR_TYPE_WRTHROUGH;
 74                         break;
 75                 }
 76         }
 77 }
 78 
 79 static int
 80 cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 81 /*  [SUMMARY] Get a free ARR.
 82     <base> The starting (base) address of the region.
 83     <size> The size (in bytes) of the region.
 84     [RETURNS] The index of the region on success, else -1 on error.
 85 */
 86 {
 87         int i;
 88         mtrr_type ltype;
 89         unsigned long lbase, lsize;
 90 
 91         switch (replace_reg) {
 92         case 7:
 93                 if (size < 0x40)
 94                         break;
 95         case 6:
 96         case 5:
 97         case 4:
 98                 return replace_reg;
 99         case 3:
100         case 2:
101         case 1:
102         case 0:
103                 return replace_reg;
104         }
105         /* If we are to set up a region >32M then look at ARR7 immediately */
106         if (size > 0x2000) {
107                 cyrix_get_arr(7, &lbase, &lsize, &ltype);
108                 if (lsize == 0)
109                         return 7;
110                 /*  Else try ARR0-ARR6 first  */
111         } else {
112                 for (i = 0; i < 7; i++) {
113                         cyrix_get_arr(i, &lbase, &lsize, &ltype);
114                         if (lsize == 0)
115                                 return i;
116                 }
117                 /* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
118                 cyrix_get_arr(i, &lbase, &lsize, &ltype);
119                 if ((lsize == 0) && (size >= 0x40))
120                         return i;
121         }
122         return -ENOSPC;
123 }
124 
125 static u32 cr4 = 0;
126 static u32 ccr3;
127 
128 static void prepare_set(void)
129 {
130         u32 cr0;
131 
132         /*  Save value of CR4 and clear Page Global Enable (bit 7)  */
133         if ( cpu_has_pge ) {
134                 cr4 = read_cr4();
135                 write_cr4(cr4 & ~X86_CR4_PGE);
136         }
137 
138         /*  Disable and flush caches. Note that wbinvd flushes the TLBs as
139             a side-effect  */
140         cr0 = read_cr0() | X86_CR0_CD;
141         wbinvd();
142         write_cr0(cr0);
143         wbinvd();
144 
145         /* Cyrix ARRs - everything else was excluded at the top */
146         ccr3 = getCx86(CX86_CCR3);
147 
148         /* Cyrix ARRs - everything else was excluded at the top */
149         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);
150 
151 }
152 
153 static void post_set(void)
154 {
155         /*  Flush caches and TLBs  */
156         wbinvd();
157 
158         /* Cyrix ARRs - everything else was excluded at the top */
159         setCx86(CX86_CCR3, ccr3);
160                 
161         /*  Enable caches  */
162         write_cr0(read_cr0() & 0xbfffffff);
163 
164         /*  Restore value of CR4  */
165         if ( cpu_has_pge )
166                 write_cr4(cr4);
167 }
168 
169 static void cyrix_set_arr(unsigned int reg, unsigned long base,
170                           unsigned long size, mtrr_type type)
171 {
172         unsigned char arr, arr_type, arr_size;
173 
174         arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
175 
176         /* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */
177         if (reg >= 7)
178                 size >>= 6;
179 
180         size &= 0x7fff;         /* make sure arr_size <= 14 */
181         for (arr_size = 0; size; arr_size++, size >>= 1) ;
182 
183         if (reg < 7) {
184                 switch (type) {
185                 case MTRR_TYPE_UNCACHABLE:
186                         arr_type = 1;
187                         break;
188                 case MTRR_TYPE_WRCOMB:
189                         arr_type = 9;
190                         break;
191                 case MTRR_TYPE_WRTHROUGH:
192                         arr_type = 24;
193                         break;
194                 default:
195                         arr_type = 8;
196                         break;
197                 }
198         } else {
199                 switch (type) {
200                 case MTRR_TYPE_UNCACHABLE:
201                         arr_type = 0;
202                         break;
203                 case MTRR_TYPE_WRCOMB:
204                         arr_type = 8;
205                         break;
206                 case MTRR_TYPE_WRTHROUGH:
207                         arr_type = 25;
208                         break;
209                 default:
210                         arr_type = 9;
211                         break;
212                 }
213         }
214 
215         prepare_set();
216 
217         base <<= PAGE_SHIFT;
218         setCx86(arr, ((unsigned char *) &base)[3]);
219         setCx86(arr + 1, ((unsigned char *) &base)[2]);
220         setCx86(arr + 2, (((unsigned char *) &base)[1]) | arr_size);
221         setCx86(CX86_RCR_BASE + reg, arr_type);
222 
223         post_set();
224 }
225 
226 typedef struct {
227         unsigned long base;
228         unsigned long size;
229         mtrr_type type;
230 } arr_state_t;
231 
232 static arr_state_t arr_state[8] = {
233         {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
234         {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
235 };
236 
237 static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
238 
239 static void cyrix_set_all(void)
240 {
241         int i;
242 
243         prepare_set();
244 
245         /* the CCRs are not contiguous */
246         for (i = 0; i < 4; i++)
247                 setCx86(CX86_CCR0 + i, ccr_state[i]);
248         for (; i < 7; i++)
249                 setCx86(CX86_CCR4 + i, ccr_state[i]);
250         for (i = 0; i < 8; i++)
251                 cyrix_set_arr(i, arr_state[i].base, 
252                               arr_state[i].size, arr_state[i].type);
253 
254         post_set();
255 }
256 
257 static struct mtrr_ops cyrix_mtrr_ops = {
258         .vendor            = X86_VENDOR_CYRIX,
259 //      .init              = cyrix_arr_init,
260         .set_all           = cyrix_set_all,
261         .set               = cyrix_set_arr,
262         .get               = cyrix_get_arr,
263         .get_free_region   = cyrix_get_free_region,
264         .validate_add_page = generic_validate_add_page,
265         .have_wrcomb       = positive_have_wrcomb,
266 };
267 
268 int __init cyrix_init_mtrr(void)
269 {
270         set_mtrr_ops(&cyrix_mtrr_ops);
271         return 0;
272 }
273 
274 //arch_initcall(cyrix_init_mtrr);
275 
  This page was automatically generated by the LXR engine.