initcpu.c revision 26985
1/*
2 * Copyright (c) KATO Takenori, 1997.
3 *
4 * All rights reserved.  Unpublished rights reserved under the copyright
5 * laws of Japan.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer as
13 *    the first lines of this file unmodified.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 *		$Id: initcpu.c,v 1.5 1997/05/31 08:45:24 kato Exp $
30 */
31
32#include "opt_cpu.h"
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>
37
38#include <machine/cpu.h>
39#include <machine/cputypes.h>
40#include <machine/md_var.h>
41#include <machine/specialreg.h>
42
43void initializecpu(void);
44#ifdef I486_CPU
45static void init_5x86(void);
46static void init_bluelightning(void);
47static void init_486dlc(void);
48static void init_cy486dx(void);
49#ifdef CPU_I486_ON_386
50static void init_i486_on_386(void);
51#endif
52static void init_6x86(void);
53#endif /* I486_CPU */
54
55#ifdef I586_CPU
56static void	init_6x86MX(void);
57#endif
58
59#ifdef I486_CPU
60/*
61 * IBM Blue Lightning
62 */
63static void
64init_bluelightning(void)
65{
66	u_long	eflags;
67
68#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
69	need_post_dma_flush = 1;
70#endif
71
72	eflags = read_eflags();
73	disable_intr();
74
75	load_cr0(rcr0() | CR0_CD | CR0_NW);
76	invd();
77
78#ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
79	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
80#else
81	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
82#endif
83	/* Enables 13MB and 0-640KB cache. */
84	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
85#ifdef CPU_BLUELIGHTNING_3X
86	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
87#else
88	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
89#endif
90
91	/* Enable caching in CR0. */
92	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
93	invd();
94	write_eflags(eflags);
95}
96
97/*
98 * Cyrix 486SLC/DLC/SR/DR series
99 */
100static void
101init_486dlc(void)
102{
103	u_long	eflags;
104	u_char	ccr0;
105
106	eflags = read_eflags();
107	disable_intr();
108	invd();
109
110	ccr0 = read_cyrix_reg(CCR0);
111#ifndef CYRIX_CACHE_WORKS
112	ccr0 |= CCR0_NC1 | CCR0_BARB;
113	write_cyrix_reg(CCR0, ccr0);
114	invd();
115#else
116	ccr0 &= ~CCR0_NC0;
117#ifndef CYRIX_CACHE_REALLY_WORKS
118	ccr0 |= CCR0_NC1 | CCR0_BARB;
119#else
120	ccr0 |= CCR0_NC1;
121#endif
122#ifdef CPU_DIRECT_MAPPED_CACHE
123	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
124#endif
125	write_cyrix_reg(CCR0, ccr0);
126
127	/* Clear non-cacheable region. */
128	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
129	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
130	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
131	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
132
133	write_cyrix_reg(0, 0);	/* dummy write */
134
135	/* Enable caching in CR0. */
136	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
137	invd();
138#endif /* !CYRIX_CACHE_WORKS */
139	write_eflags(eflags);
140}
141
142
143/*
144 * Cyrix 486S/DX series
145 */
146static void
147init_cy486dx(void)
148{
149	u_long	eflags;
150	u_char	ccr2;
151
152	eflags = read_eflags();
153	disable_intr();
154	invd();
155
156	ccr2 = read_cyrix_reg(CCR2);
157#ifdef SUSP_HLT
158	ccr2 |= CCR2_SUSP_HTL;
159#endif
160	write_cyrix_reg(CCR2, ccr2);
161	write_eflags(eflags);
162}
163
164
165/*
166 * Cyrix 5x86
167 */
168static void
169init_5x86(void)
170{
171	u_long	eflags;
172	u_char	ccr2, ccr3, ccr4, pcr0;
173
174	eflags = read_eflags();
175	disable_intr();
176
177	load_cr0(rcr0() | CR0_CD | CR0_NW);
178	wbinvd();
179
180	(void)read_cyrix_reg(CCR3);		/* dummy */
181
182	/* Initialize CCR2. */
183	ccr2 = read_cyrix_reg(CCR2);
184	ccr2 |= CCR2_WB;
185#ifdef CPU_SUSP_HLT
186	ccr2 |= CCR2_SUSP_HLT;
187#else
188	ccr2 &= ~CCR2_SUSP_HLT;
189#endif
190	ccr2 |= CCR2_WT1;
191	write_cyrix_reg(CCR2, ccr2);
192
193	/* Initialize CCR4. */
194	ccr3 = read_cyrix_reg(CCR3);
195	write_cyrix_reg(CCR3, CCR3_MAPEN0);
196
197	ccr4 = read_cyrix_reg(CCR4);
198	ccr4 |= CCR4_DTE;
199	ccr4 |= CCR4_MEM;
200#ifdef CPU_FASTER_5X86_FPU
201	ccr4 |= CCR4_FASTFPE;
202#else
203	ccr4 &= ~CCR4_FASTFPE;
204#endif
205	ccr4 &= ~CCR4_IOMASK;
206	/********************************************************************
207	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
208	 * should be 0 for errata fix.
209	 ********************************************************************/
210#ifdef CPU_IORT
211	ccr4 |= CPU_IORT & CCR4_IOMASK;
212#endif
213	write_cyrix_reg(CCR4, ccr4);
214
215	/* Initialize PCR0. */
216	/****************************************************************
217	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
218	 * BTB_EN might make your system unstable.
219	 ****************************************************************/
220	pcr0 = read_cyrix_reg(PCR0);
221#ifdef CPU_RSTK_EN
222	pcr0 |= PCR0_RSTK;
223#else
224	pcr0 &= ~PCR0_RSTK;
225#endif
226#ifdef CPU_BTB_EN
227	pcr0 |= PCR0_BTB;
228#else
229	pcr0 &= ~PCR0_BTB;
230#endif
231#ifdef CPU_LOOP_EN
232	pcr0 |= PCR0_LOOP;
233#else
234	pcr0 &= ~PCR0_LOOP;
235#endif
236
237	/****************************************************************
238	 * WARNING: if you use a memory mapped I/O device, don't use
239	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
240	 * I/O access.
241	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
242	 ****************************************************************/
243#ifdef CPU_DISABLE_5X86_LSSER
244	pcr0 &= ~PCR0_LSSER;
245#else
246	pcr0 |= PCR0_LSSER;
247#endif
248	write_cyrix_reg(PCR0, pcr0);
249
250	/* Restore CCR3. */
251	write_cyrix_reg(CCR3, ccr3);
252
253	(void)read_cyrix_reg(0x80);		/* dummy */
254
255	/* Unlock NW bit in CR0. */
256	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
257	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
258	/* Lock NW bit in CR0. */
259	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
260
261	write_eflags(eflags);
262}
263
264#ifdef CPU_I486_ON_386
265/*
266 * There are i486 based upgrade products for i386 machines.
267 * In this case, BIOS doesn't enables CPU cache.
268 */
269void
270init_i486_on_386(void)
271{
272	u_long	eflags;
273
274#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
275	need_post_dma_flush = 1;
276#endif
277
278	eflags = read_eflags();
279	disable_intr();
280
281	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
282
283	write_eflags(eflags);
284}
285#endif
286
287/*
288 * Cyrix 6x86
289 *
290 * XXX - What should I do here?  Please let me know.
291 */
292static void
293init_6x86(void)
294{
295	u_long	eflags;
296	u_char	ccr3, ccr4;
297
298	eflags = read_eflags();
299	disable_intr();
300
301	load_cr0(rcr0() | CR0_CD | CR0_NW);
302	wbinvd();
303
304	/* Initialize CCR0. */
305	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
306
307	/* Initialize CCR2. */
308#ifdef CPU_SUSP_HLT
309	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
310#else
311	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
312#endif
313
314	ccr3 = read_cyrix_reg(CCR3);
315	write_cyrix_reg(CCR3, CCR3_MAPEN0);
316
317	/* Initialize CCR4. */
318	ccr4 = read_cyrix_reg(CCR4);
319	ccr4 |= CCR4_DTE;
320	ccr4 &= ~CCR4_IOMASK;
321#ifdef CPU_IORT
322	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
323#else
324	write_cyrix_reg(CCR4, ccr4 | 7);
325#endif
326
327	/* Restore CCR3. */
328	write_cyrix_reg(CCR3, ccr3);
329
330	/* Unlock NW bit in CR0. */
331	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
332
333	/*
334	 * Earlier revision of the 6x86 CPU could crash the system if
335	 * L1 cache is in write-back mode.
336	 */
337	if ((cyrix_did & 0xff00) > 0x1600)
338		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
339	else {
340		/* Revision 2.6 and lower. */
341#ifdef CYRIX_CACHE_REALLY_WORKS
342		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
343#else
344		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
345#endif
346	}
347
348	/* Lock NW bit in CR0. */
349	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
350
351	write_eflags(eflags);
352}
353#endif /* I486_CPU */
354
355#ifdef I586_CPU
356/*
357 * Cyrix 6x86MX (code-named M2)
358 *
359 * XXX - What should I do here?  Please let me know.
360 */
361static void
362init_6x86MX(void)
363{
364	u_long	eflags;
365	u_char	ccr3, ccr4;
366
367	eflags = read_eflags();
368	disable_intr();
369
370	load_cr0(rcr0() | CR0_CD | CR0_NW);
371	wbinvd();
372
373	/* Initialize CCR0. */
374	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
375
376	/* Initialize CCR2. */
377#ifdef CPU_SUSP_HLT
378	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
379#else
380	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
381#endif
382
383	ccr3 = read_cyrix_reg(CCR3);
384	write_cyrix_reg(CCR3, CCR3_MAPEN0);
385
386	/* Initialize CCR4. */
387	ccr4 = read_cyrix_reg(CCR4);
388	ccr4 &= ~CCR4_IOMASK;
389#ifdef CPU_IORT
390	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
391#else
392	write_cyrix_reg(CCR4, ccr4 | 7);
393#endif
394
395	/* Restore CCR3. */
396	write_cyrix_reg(CCR3, ccr3);
397
398	/* Unlock NW bit in CR0. */
399	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
400
401	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
402
403	/* Lock NW bit in CR0. */
404	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
405
406	write_eflags(eflags);
407}
408#endif /* I586_CPU */
409
410void
411initializecpu(void)
412{
413
414	switch (cpu) {
415#ifdef I486_CPU
416	case CPU_BLUE:
417		init_bluelightning();
418		break;
419	case CPU_486DLC:
420		init_486dlc();
421		break;
422	case CPU_CY486DX:
423		init_cy486dx();
424		break;
425	case CPU_M1SC:
426		init_5x86();
427		break;
428#ifdef CPU_I486_ON_386
429	case CPU_486:
430		init_i486_on_386();
431		break;
432#endif
433	case CPU_M1:
434		init_6x86();
435		break;
436#endif /* I486_CPU */
437#ifdef I586_CPU
438	case CPU_M2:
439		init_6x86MX();
440		break;
441#endif
442	default:
443		break;
444	}
445
446#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
447	/*
448	 * OS should flush L1 cahce by itself because no PC-98 supports
449	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
450	 * when need_pre_dma_flush = 1, use invd instruction after DMA
451	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
452	 * product support hardware cache control, you can add
453	 * UPGRADE_CPU_HW_CACHE option in your kernel configuration file.
454	 * This option elminate unneeded cache flush instruction.
455	 */
456	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
457		switch (cpu) {
458#ifdef I486_CPU
459		case CPU_486DLC:
460			need_post_dma_flush = 1;
461			break;
462		case CPU_M1SC:
463			need_pre_dma_flush = 1;
464			break;
465#endif
466		default:
467			break;
468		}
469	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
470		switch (cpu_id & 0xFF0) {
471		case 0x470:		/* Enhanced Am486DX2 WB */
472		case 0x490:		/* Enhanced Am486DX4 WB */
473		case 0x4F0:		/* Am5x86 WB */
474			need_pre_dma_flush = 1;
475			break;
476		}
477	} else if (strcmp(cpu_vendor, "IBM") == 0) {
478		need_post_dma_flush = 1;
479	} else {
480#ifdef CPU_I486_ON_386
481		need_pre_dma_flush = 1;
482#endif
483	}
484#endif /* PC98 && !UPGRADE_CPU_HW_CACHE */
485}
486
487#include "opt_ddb.h"
488#ifdef DDB
489#include <ddb/ddb.h>
490
491DB_SHOW_COMMAND(cyrixreg, cyrixreg)
492{
493	u_long	eflags;
494	u_int	cr0;
495	u_char	ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, pcr0;
496
497	cr0 = rcr0();
498	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
499		eflags = read_eflags();
500		disable_intr();
501
502
503		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
504			ccr0 = read_cyrix_reg(CCR0);
505		}
506		ccr1 = read_cyrix_reg(CCR1);
507		ccr2 = read_cyrix_reg(CCR2);
508		ccr3 = read_cyrix_reg(CCR3);
509		if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) {
510			write_cyrix_reg(CCR3, CCR3_MAPEN0);
511			ccr4 = read_cyrix_reg(CCR4);
512			if (cpu == CPU_M1)
513				ccr5 = read_cyrix_reg(CCR5);
514			else
515				pcr0 = read_cyrix_reg(PCR0);
516			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
517		}
518		write_eflags(eflags);
519
520		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
521			printf("CCR0=%x, ", (u_int)ccr0);
522
523		printf("CCR1=%x, CCR2=%x, CCR3=%x",
524			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
525		if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) {
526			printf(", CCR4=%x, ", (u_int)ccr4);
527			if (cpu == CPU_M1)
528				printf("CCR5=%x\n", ccr5);
529			else
530				printf("PCR0=%x\n", pcr0);
531		}
532	}
533	printf("CR0=%x\n", cr0);
534}
535#endif /* DDB */
536