diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha/kernel/core_lca.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/alpha/kernel/core_lca.c')
-rw-r--r-- | arch/alpha/kernel/core_lca.c | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c new file mode 100644 index 000000000000..6a5a9145c676 --- /dev/null +++ b/arch/alpha/kernel/core_lca.c | |||
@@ -0,0 +1,515 @@ | |||
1 | /* | ||
2 | * linux/arch/alpha/kernel/core_lca.c | ||
3 | * | ||
4 | * Written by David Mosberger (davidm@cs.arizona.edu) with some code | ||
5 | * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit | ||
6 | * bios code. | ||
7 | * | ||
8 | * Code common to all LCA core logic chips. | ||
9 | */ | ||
10 | |||
11 | #define __EXTERN_INLINE inline | ||
12 | #include <asm/io.h> | ||
13 | #include <asm/core_lca.h> | ||
14 | #undef __EXTERN_INLINE | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/tty.h> | ||
20 | |||
21 | #include <asm/ptrace.h> | ||
22 | #include <asm/smp.h> | ||
23 | |||
24 | #include "proto.h" | ||
25 | #include "pci_impl.h" | ||
26 | |||
27 | |||
28 | /* | ||
29 | * BIOS32-style PCI interface: | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * Machine check reasons. Defined according to PALcode sources | ||
34 | * (osf.h and platform.h). | ||
35 | */ | ||
36 | #define MCHK_K_TPERR 0x0080 | ||
37 | #define MCHK_K_TCPERR 0x0082 | ||
38 | #define MCHK_K_HERR 0x0084 | ||
39 | #define MCHK_K_ECC_C 0x0086 | ||
40 | #define MCHK_K_ECC_NC 0x0088 | ||
41 | #define MCHK_K_UNKNOWN 0x008A | ||
42 | #define MCHK_K_CACKSOFT 0x008C | ||
43 | #define MCHK_K_BUGCHECK 0x008E | ||
44 | #define MCHK_K_OS_BUGCHECK 0x0090 | ||
45 | #define MCHK_K_DCPERR 0x0092 | ||
46 | #define MCHK_K_ICPERR 0x0094 | ||
47 | |||
48 | |||
49 | /* | ||
50 | * Platform-specific machine-check reasons: | ||
51 | */ | ||
52 | #define MCHK_K_SIO_SERR 0x204 /* all platforms so far */ | ||
53 | #define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */ | ||
54 | #define MCHK_K_DCSR 0x208 /* all but Noname */ | ||
55 | |||
56 | |||
57 | /* | ||
58 | * Given a bus, device, and function number, compute resulting | ||
59 | * configuration space address and setup the LCA_IOC_CONF register | ||
60 | * accordingly. It is therefore not safe to have concurrent | ||
61 | * invocations to configuration space access routines, but there | ||
62 | * really shouldn't be any need for this. | ||
63 | * | ||
64 | * Type 0: | ||
65 | * | ||
66 | * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 | ||
67 | * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 | ||
68 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
69 | * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| | ||
70 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
71 | * | ||
72 | * 31:11 Device select bit. | ||
73 | * 10:8 Function number | ||
74 | * 7:2 Register number | ||
75 | * | ||
76 | * Type 1: | ||
77 | * | ||
78 | * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 | ||
79 | * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 | ||
80 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
81 | * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| | ||
82 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
83 | * | ||
84 | * 31:24 reserved | ||
85 | * 23:16 bus number (8 bits = 128 possible buses) | ||
86 | * 15:11 Device number (5 bits) | ||
87 | * 10:8 function number | ||
88 | * 7:2 register number | ||
89 | * | ||
90 | * Notes: | ||
91 | * The function number selects which function of a multi-function device | ||
92 | * (e.g., SCSI and Ethernet). | ||
93 | * | ||
94 | * The register selects a DWORD (32 bit) register offset. Hence it | ||
95 | * doesn't get shifted by 2 bits as we want to "drop" the bottom two | ||
96 | * bits. | ||
97 | */ | ||
98 | |||
99 | static int | ||
100 | mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, | ||
101 | unsigned long *pci_addr) | ||
102 | { | ||
103 | unsigned long addr; | ||
104 | u8 bus = pbus->number; | ||
105 | |||
106 | if (bus == 0) { | ||
107 | int device = device_fn >> 3; | ||
108 | int func = device_fn & 0x7; | ||
109 | |||
110 | /* Type 0 configuration cycle. */ | ||
111 | |||
112 | if (device > 12) { | ||
113 | return -1; | ||
114 | } | ||
115 | |||
116 | *(vulp)LCA_IOC_CONF = 0; | ||
117 | addr = (1 << (11 + device)) | (func << 8) | where; | ||
118 | } else { | ||
119 | /* Type 1 configuration cycle. */ | ||
120 | *(vulp)LCA_IOC_CONF = 1; | ||
121 | addr = (bus << 16) | (device_fn << 8) | where; | ||
122 | } | ||
123 | *pci_addr = addr; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static unsigned int | ||
128 | conf_read(unsigned long addr) | ||
129 | { | ||
130 | unsigned long flags, code, stat0; | ||
131 | unsigned int value; | ||
132 | |||
133 | local_irq_save(flags); | ||
134 | |||
135 | /* Reset status register to avoid loosing errors. */ | ||
136 | stat0 = *(vulp)LCA_IOC_STAT0; | ||
137 | *(vulp)LCA_IOC_STAT0 = stat0; | ||
138 | mb(); | ||
139 | |||
140 | /* Access configuration space. */ | ||
141 | value = *(vuip)addr; | ||
142 | draina(); | ||
143 | |||
144 | stat0 = *(vulp)LCA_IOC_STAT0; | ||
145 | if (stat0 & LCA_IOC_STAT0_ERR) { | ||
146 | code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) | ||
147 | & LCA_IOC_STAT0_CODE_MASK); | ||
148 | if (code != 1) { | ||
149 | printk("lca.c:conf_read: got stat0=%lx\n", stat0); | ||
150 | } | ||
151 | |||
152 | /* Reset error status. */ | ||
153 | *(vulp)LCA_IOC_STAT0 = stat0; | ||
154 | mb(); | ||
155 | |||
156 | /* Reset machine check. */ | ||
157 | wrmces(0x7); | ||
158 | |||
159 | value = 0xffffffff; | ||
160 | } | ||
161 | local_irq_restore(flags); | ||
162 | return value; | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | conf_write(unsigned long addr, unsigned int value) | ||
167 | { | ||
168 | unsigned long flags, code, stat0; | ||
169 | |||
170 | local_irq_save(flags); /* avoid getting hit by machine check */ | ||
171 | |||
172 | /* Reset status register to avoid loosing errors. */ | ||
173 | stat0 = *(vulp)LCA_IOC_STAT0; | ||
174 | *(vulp)LCA_IOC_STAT0 = stat0; | ||
175 | mb(); | ||
176 | |||
177 | /* Access configuration space. */ | ||
178 | *(vuip)addr = value; | ||
179 | draina(); | ||
180 | |||
181 | stat0 = *(vulp)LCA_IOC_STAT0; | ||
182 | if (stat0 & LCA_IOC_STAT0_ERR) { | ||
183 | code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) | ||
184 | & LCA_IOC_STAT0_CODE_MASK); | ||
185 | if (code != 1) { | ||
186 | printk("lca.c:conf_write: got stat0=%lx\n", stat0); | ||
187 | } | ||
188 | |||
189 | /* Reset error status. */ | ||
190 | *(vulp)LCA_IOC_STAT0 = stat0; | ||
191 | mb(); | ||
192 | |||
193 | /* Reset machine check. */ | ||
194 | wrmces(0x7); | ||
195 | } | ||
196 | local_irq_restore(flags); | ||
197 | } | ||
198 | |||
199 | static int | ||
200 | lca_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
201 | int size, u32 *value) | ||
202 | { | ||
203 | unsigned long addr, pci_addr; | ||
204 | long mask; | ||
205 | int shift; | ||
206 | |||
207 | if (mk_conf_addr(bus, devfn, where, &pci_addr)) | ||
208 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
209 | |||
210 | shift = (where & 3) * 8; | ||
211 | mask = (size - 1) * 8; | ||
212 | addr = (pci_addr << 5) + mask + LCA_CONF; | ||
213 | *value = conf_read(addr) >> (shift); | ||
214 | return PCIBIOS_SUCCESSFUL; | ||
215 | } | ||
216 | |||
217 | static int | ||
218 | lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, | ||
219 | u32 value) | ||
220 | { | ||
221 | unsigned long addr, pci_addr; | ||
222 | long mask; | ||
223 | |||
224 | if (mk_conf_addr(bus, devfn, where, &pci_addr)) | ||
225 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
226 | |||
227 | mask = (size - 1) * 8; | ||
228 | addr = (pci_addr << 5) + mask + LCA_CONF; | ||
229 | conf_write(addr, value << ((where & 3) * 8)); | ||
230 | return PCIBIOS_SUCCESSFUL; | ||
231 | } | ||
232 | |||
233 | struct pci_ops lca_pci_ops = | ||
234 | { | ||
235 | .read = lca_read_config, | ||
236 | .write = lca_write_config, | ||
237 | }; | ||
238 | |||
239 | void | ||
240 | lca_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) | ||
241 | { | ||
242 | wmb(); | ||
243 | *(vulp)LCA_IOC_TBIA = 0; | ||
244 | mb(); | ||
245 | } | ||
246 | |||
247 | void __init | ||
248 | lca_init_arch(void) | ||
249 | { | ||
250 | struct pci_controller *hose; | ||
251 | |||
252 | /* | ||
253 | * Create our single hose. | ||
254 | */ | ||
255 | |||
256 | pci_isa_hose = hose = alloc_pci_controller(); | ||
257 | hose->io_space = &ioport_resource; | ||
258 | hose->mem_space = &iomem_resource; | ||
259 | hose->index = 0; | ||
260 | |||
261 | hose->sparse_mem_base = LCA_SPARSE_MEM - IDENT_ADDR; | ||
262 | hose->dense_mem_base = LCA_DENSE_MEM - IDENT_ADDR; | ||
263 | hose->sparse_io_base = LCA_IO - IDENT_ADDR; | ||
264 | hose->dense_io_base = 0; | ||
265 | |||
266 | /* | ||
267 | * Set up the PCI to main memory translation windows. | ||
268 | * | ||
269 | * Mimic the SRM settings for the direct-map window. | ||
270 | * Window 0 is scatter-gather 8MB at 8MB (for isa). | ||
271 | * Window 1 is direct access 1GB at 1GB. | ||
272 | * | ||
273 | * Note that we do not try to save any of the DMA window CSRs | ||
274 | * before setting them, since we cannot read those CSRs on LCA. | ||
275 | */ | ||
276 | hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); | ||
277 | hose->sg_pci = NULL; | ||
278 | __direct_map_base = 0x40000000; | ||
279 | __direct_map_size = 0x40000000; | ||
280 | |||
281 | *(vulp)LCA_IOC_W_BASE0 = hose->sg_isa->dma_base | (3UL << 32); | ||
282 | *(vulp)LCA_IOC_W_MASK0 = (hose->sg_isa->size - 1) & 0xfff00000; | ||
283 | *(vulp)LCA_IOC_T_BASE0 = virt_to_phys(hose->sg_isa->ptes); | ||
284 | |||
285 | *(vulp)LCA_IOC_W_BASE1 = __direct_map_base | (2UL << 32); | ||
286 | *(vulp)LCA_IOC_W_MASK1 = (__direct_map_size - 1) & 0xfff00000; | ||
287 | *(vulp)LCA_IOC_T_BASE1 = 0; | ||
288 | |||
289 | *(vulp)LCA_IOC_TB_ENA = 0x80; | ||
290 | |||
291 | lca_pci_tbi(hose, 0, -1); | ||
292 | |||
293 | /* | ||
294 | * Disable PCI parity for now. The NCR53c810 chip has | ||
295 | * troubles meeting the PCI spec which results in | ||
296 | * data parity errors. | ||
297 | */ | ||
298 | *(vulp)LCA_IOC_PAR_DIS = 1UL<<5; | ||
299 | |||
300 | /* | ||
301 | * Finally, set up for restoring the correct HAE if using SRM. | ||
302 | * Again, since we cannot read many of the CSRs on the LCA, | ||
303 | * one of which happens to be the HAE, we save the value that | ||
304 | * the SRM will expect... | ||
305 | */ | ||
306 | if (alpha_using_srm) | ||
307 | srm_hae = 0x80000000UL; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Constants used during machine-check handling. I suppose these | ||
312 | * could be moved into lca.h but I don't see much reason why anybody | ||
313 | * else would want to use them. | ||
314 | */ | ||
315 | |||
316 | #define ESR_EAV (1UL<< 0) /* error address valid */ | ||
317 | #define ESR_CEE (1UL<< 1) /* correctable error */ | ||
318 | #define ESR_UEE (1UL<< 2) /* uncorrectable error */ | ||
319 | #define ESR_WRE (1UL<< 3) /* write-error */ | ||
320 | #define ESR_SOR (1UL<< 4) /* error source */ | ||
321 | #define ESR_CTE (1UL<< 7) /* cache-tag error */ | ||
322 | #define ESR_MSE (1UL<< 9) /* multiple soft errors */ | ||
323 | #define ESR_MHE (1UL<<10) /* multiple hard errors */ | ||
324 | #define ESR_NXM (1UL<<12) /* non-existent memory */ | ||
325 | |||
326 | #define IOC_ERR ( 1<<4) /* ioc logs an error */ | ||
327 | #define IOC_CMD_SHIFT 0 | ||
328 | #define IOC_CMD (0xf<<IOC_CMD_SHIFT) | ||
329 | #define IOC_CODE_SHIFT 8 | ||
330 | #define IOC_CODE (0xf<<IOC_CODE_SHIFT) | ||
331 | #define IOC_LOST ( 1<<5) | ||
332 | #define IOC_P_NBR ((__u32) ~((1<<13) - 1)) | ||
333 | |||
334 | static void | ||
335 | mem_error(unsigned long esr, unsigned long ear) | ||
336 | { | ||
337 | printk(" %s %s error to %s occurred at address %x\n", | ||
338 | ((esr & ESR_CEE) ? "Correctable" : | ||
339 | (esr & ESR_UEE) ? "Uncorrectable" : "A"), | ||
340 | (esr & ESR_WRE) ? "write" : "read", | ||
341 | (esr & ESR_SOR) ? "memory" : "b-cache", | ||
342 | (unsigned) (ear & 0x1ffffff8)); | ||
343 | if (esr & ESR_CTE) { | ||
344 | printk(" A b-cache tag parity error was detected.\n"); | ||
345 | } | ||
346 | if (esr & ESR_MSE) { | ||
347 | printk(" Several other correctable errors occurred.\n"); | ||
348 | } | ||
349 | if (esr & ESR_MHE) { | ||
350 | printk(" Several other uncorrectable errors occurred.\n"); | ||
351 | } | ||
352 | if (esr & ESR_NXM) { | ||
353 | printk(" Attempted to access non-existent memory.\n"); | ||
354 | } | ||
355 | } | ||
356 | |||
357 | static void | ||
358 | ioc_error(__u32 stat0, __u32 stat1) | ||
359 | { | ||
360 | static const char * const pci_cmd[] = { | ||
361 | "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write", | ||
362 | "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3", | ||
363 | "Rsvd4", "Configuration Read", "Configuration Write", | ||
364 | "Memory Read Multiple", "Dual Address", "Memory Read Line", | ||
365 | "Memory Write and Invalidate" | ||
366 | }; | ||
367 | static const char * const err_name[] = { | ||
368 | "exceeded retry limit", "no device", "bad data parity", | ||
369 | "target abort", "bad address parity", "page table read error", | ||
370 | "invalid page", "data error" | ||
371 | }; | ||
372 | unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT; | ||
373 | unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT; | ||
374 | |||
375 | printk(" %s initiated PCI %s cycle to address %x" | ||
376 | " failed due to %s.\n", | ||
377 | code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]); | ||
378 | |||
379 | if (code == 5 || code == 6) { | ||
380 | printk(" (Error occurred at PCI memory address %x.)\n", | ||
381 | (stat0 & ~IOC_P_NBR)); | ||
382 | } | ||
383 | if (stat0 & IOC_LOST) { | ||
384 | printk(" Other PCI errors occurred simultaneously.\n"); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | void | ||
389 | lca_machine_check(unsigned long vector, unsigned long la_ptr, | ||
390 | struct pt_regs *regs) | ||
391 | { | ||
392 | const char * reason; | ||
393 | union el_lca el; | ||
394 | |||
395 | el.c = (struct el_common *) la_ptr; | ||
396 | |||
397 | wrmces(rdmces()); /* reset machine check pending flag */ | ||
398 | |||
399 | printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n", | ||
400 | vector, regs->pc, (unsigned int) el.c->code); | ||
401 | |||
402 | /* | ||
403 | * The first quadword after the common header always seems to | ||
404 | * be the machine check reason---don't know why this isn't | ||
405 | * part of the common header instead. In the case of a long | ||
406 | * logout frame, the upper 32 bits is the machine check | ||
407 | * revision level, which we ignore for now. | ||
408 | */ | ||
409 | switch ((unsigned int) el.c->code) { | ||
410 | case MCHK_K_TPERR: reason = "tag parity error"; break; | ||
411 | case MCHK_K_TCPERR: reason = "tag control parity error"; break; | ||
412 | case MCHK_K_HERR: reason = "access to non-existent memory"; break; | ||
413 | case MCHK_K_ECC_C: reason = "correctable ECC error"; break; | ||
414 | case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break; | ||
415 | case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; | ||
416 | case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break; | ||
417 | case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; | ||
418 | case MCHK_K_DCPERR: reason = "d-cache parity error"; break; | ||
419 | case MCHK_K_ICPERR: reason = "i-cache parity error"; break; | ||
420 | case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on PCI bus"; break; | ||
421 | case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; | ||
422 | case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; | ||
423 | case MCHK_K_UNKNOWN: | ||
424 | default: reason = "unknown"; break; | ||
425 | } | ||
426 | |||
427 | switch (el.c->size) { | ||
428 | case sizeof(struct el_lca_mcheck_short): | ||
429 | printk(KERN_CRIT | ||
430 | " Reason: %s (short frame%s, dc_stat=%#lx):\n", | ||
431 | reason, el.c->retry ? ", retryable" : "", | ||
432 | el.s->dc_stat); | ||
433 | if (el.s->esr & ESR_EAV) { | ||
434 | mem_error(el.s->esr, el.s->ear); | ||
435 | } | ||
436 | if (el.s->ioc_stat0 & IOC_ERR) { | ||
437 | ioc_error(el.s->ioc_stat0, el.s->ioc_stat1); | ||
438 | } | ||
439 | break; | ||
440 | |||
441 | case sizeof(struct el_lca_mcheck_long): | ||
442 | printk(KERN_CRIT " Reason: %s (long frame%s):\n", | ||
443 | reason, el.c->retry ? ", retryable" : ""); | ||
444 | printk(KERN_CRIT | ||
445 | " reason: %#lx exc_addr: %#lx dc_stat: %#lx\n", | ||
446 | el.l->pt[0], el.l->exc_addr, el.l->dc_stat); | ||
447 | printk(KERN_CRIT " car: %#lx\n", el.l->car); | ||
448 | if (el.l->esr & ESR_EAV) { | ||
449 | mem_error(el.l->esr, el.l->ear); | ||
450 | } | ||
451 | if (el.l->ioc_stat0 & IOC_ERR) { | ||
452 | ioc_error(el.l->ioc_stat0, el.l->ioc_stat1); | ||
453 | } | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size); | ||
458 | } | ||
459 | |||
460 | /* Dump the logout area to give all info. */ | ||
461 | #ifdef CONFIG_VERBOSE_MCHECK | ||
462 | if (alpha_verbose_mcheck > 1) { | ||
463 | unsigned long * ptr = (unsigned long *) la_ptr; | ||
464 | long i; | ||
465 | for (i = 0; i < el.c->size / sizeof(long); i += 2) { | ||
466 | printk(KERN_CRIT " +%8lx %016lx %016lx\n", | ||
467 | i*sizeof(long), ptr[i], ptr[i+1]); | ||
468 | } | ||
469 | } | ||
470 | #endif /* CONFIG_VERBOSE_MCHECK */ | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * The following routines are needed to support the SPEED changing | ||
475 | * necessary to successfully manage the thermal problem on the AlphaBook1. | ||
476 | */ | ||
477 | |||
478 | void | ||
479 | lca_clock_print(void) | ||
480 | { | ||
481 | long pmr_reg; | ||
482 | |||
483 | pmr_reg = LCA_READ_PMR; | ||
484 | |||
485 | printk("Status of clock control:\n"); | ||
486 | printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg)); | ||
487 | printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg)); | ||
488 | printk("\tInterrupt override is %s\n", | ||
489 | (pmr_reg & LCA_PMR_INTO) ? "on" : "off"); | ||
490 | printk("\tDMA override is %s\n", | ||
491 | (pmr_reg & LCA_PMR_DMAO) ? "on" : "off"); | ||
492 | |||
493 | } | ||
494 | |||
495 | int | ||
496 | lca_get_clock(void) | ||
497 | { | ||
498 | long pmr_reg; | ||
499 | |||
500 | pmr_reg = LCA_READ_PMR; | ||
501 | return(LCA_GET_PRIMARY(pmr_reg)); | ||
502 | |||
503 | } | ||
504 | |||
505 | void | ||
506 | lca_clock_fiddle(int divisor) | ||
507 | { | ||
508 | long pmr_reg; | ||
509 | |||
510 | pmr_reg = LCA_READ_PMR; | ||
511 | LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor); | ||
512 | /* lca_norm_clock = divisor; */ | ||
513 | LCA_WRITE_PMR(pmr_reg); | ||
514 | mb(); | ||
515 | } | ||