1 |
1622 |
jcastillo |
/*
|
2 |
|
|
* linux/arch/alpha/kernel/setup.c
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1995 Linus Torvalds
|
5 |
|
|
*/
|
6 |
|
|
|
7 |
|
|
/*
|
8 |
|
|
* bootup setup stuff..
|
9 |
|
|
*/
|
10 |
|
|
|
11 |
|
|
#include <linux/errno.h>
|
12 |
|
|
#include <linux/sched.h>
|
13 |
|
|
#include <linux/kernel.h>
|
14 |
|
|
#include <linux/mm.h>
|
15 |
|
|
#include <linux/stddef.h>
|
16 |
|
|
#include <linux/unistd.h>
|
17 |
|
|
#include <linux/ptrace.h>
|
18 |
|
|
#include <linux/malloc.h>
|
19 |
|
|
#include <linux/ldt.h>
|
20 |
|
|
#include <linux/user.h>
|
21 |
|
|
#include <linux/a.out.h>
|
22 |
|
|
#include <linux/tty.h>
|
23 |
|
|
#include <linux/delay.h>
|
24 |
|
|
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
|
25 |
|
|
#include <linux/mc146818rtc.h>
|
26 |
|
|
|
27 |
|
|
#include <asm/segment.h>
|
28 |
|
|
#include <asm/pgtable.h>
|
29 |
|
|
#include <asm/system.h>
|
30 |
|
|
#include <asm/hwrpb.h>
|
31 |
|
|
#include <asm/dma.h>
|
32 |
|
|
#include <asm/io.h>
|
33 |
|
|
|
34 |
|
|
struct hae hae = {
|
35 |
|
|
0,
|
36 |
|
|
(unsigned long*) HAE_ADDRESS
|
37 |
|
|
};
|
38 |
|
|
|
39 |
|
|
struct hwrpb_struct *hwrpb;
|
40 |
|
|
|
41 |
|
|
unsigned char aux_device_present = 0xaa;
|
42 |
|
|
|
43 |
|
|
/*
|
44 |
|
|
* This is setup by the secondary bootstrap loader. Because
|
45 |
|
|
* the zero page is zeroed out as soon as the vm system is
|
46 |
|
|
* initialized, we need to copy things out into a more permanent
|
47 |
|
|
* place.
|
48 |
|
|
*/
|
49 |
|
|
#define PARAM ZERO_PAGE
|
50 |
|
|
#define COMMAND_LINE ((char*)(PARAM + 0x0000))
|
51 |
|
|
#define COMMAND_LINE_SIZE 256
|
52 |
|
|
|
53 |
|
|
static char command_line[COMMAND_LINE_SIZE] = { 0, };
|
54 |
|
|
char saved_command_line[COMMAND_LINE_SIZE];
|
55 |
|
|
|
56 |
|
|
/*
|
57 |
|
|
* The format of "screen_info" is strange, and due to early
|
58 |
|
|
* i386-setup code. This is just enough to make the console
|
59 |
|
|
* code think we're on a VGA color display.
|
60 |
|
|
*/
|
61 |
|
|
struct screen_info screen_info = {
|
62 |
|
|
#if defined(CONFIG_ALPHA_BOOK1)
|
63 |
|
|
/* the AlphaBook1 has LCD video fixed at 800x600, 37 rows and 100 cols */
|
64 |
|
|
0, 37, /* orig-x, orig-y */
|
65 |
|
|
#else
|
66 |
|
|
0, 25, /* orig-x, orig-y */
|
67 |
|
|
#endif
|
68 |
|
|
{ 0, 0 }, /* unused */
|
69 |
|
|
0, /* orig-video-page */
|
70 |
|
|
0, /* orig-video-mode */
|
71 |
|
|
#if defined(CONFIG_ALPHA_BOOK1)
|
72 |
|
|
100, /* orig-video-cols */
|
73 |
|
|
#else
|
74 |
|
|
80, /* orig-video-cols */
|
75 |
|
|
#endif
|
76 |
|
|
0,0,0, /* ega_ax, ega_bx, ega_cx */
|
77 |
|
|
#if defined(CONFIG_ALPHA_BOOK1)
|
78 |
|
|
37, /* orig-video-lines */
|
79 |
|
|
#else
|
80 |
|
|
25, /* orig-video-lines */
|
81 |
|
|
#endif
|
82 |
|
|
1, /* orig-video-isVGA */
|
83 |
|
|
16 /* orig-video-points */
|
84 |
|
|
};
|
85 |
|
|
|
86 |
|
|
/*
|
87 |
|
|
* Initialize Programmable Interval Timers with standard values. Some
|
88 |
|
|
* drivers depend on them being initialized (e.g., joystick driver).
|
89 |
|
|
*/
|
90 |
|
|
static void init_pit (void)
|
91 |
|
|
{
|
92 |
|
|
#if 0
|
93 |
|
|
/*
|
94 |
|
|
* Leave refresh timer alone---nobody should depend on
|
95 |
|
|
* a particular value anyway.
|
96 |
|
|
*/
|
97 |
|
|
outb(0x54, 0x43); /* counter 1: refresh timer */
|
98 |
|
|
outb(0x18, 0x41);
|
99 |
|
|
#endif
|
100 |
|
|
|
101 |
|
|
#if !defined(CONFIG_ALPHA_RUFFIAN)
|
102 |
|
|
/* Ruffian depends on the system timer established in MILO!! */
|
103 |
|
|
outb(0x36, 0x43); /* counter 0: system timer */
|
104 |
|
|
outb(0x00, 0x40);
|
105 |
|
|
outb(0x00, 0x40);
|
106 |
|
|
#endif /* RUFFIAN */
|
107 |
|
|
|
108 |
|
|
outb(0xb6, 0x43); /* counter 2: speaker */
|
109 |
|
|
outb(0x31, 0x42);
|
110 |
|
|
outb(0x13, 0x42);
|
111 |
|
|
}
|
112 |
|
|
|
113 |
|
|
static unsigned long find_end_memory(void)
|
114 |
|
|
{
|
115 |
|
|
int i;
|
116 |
|
|
unsigned long high = 0;
|
117 |
|
|
struct memclust_struct * cluster;
|
118 |
|
|
struct memdesc_struct * memdesc;
|
119 |
|
|
|
120 |
|
|
memdesc = (struct memdesc_struct *)
|
121 |
|
|
(INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
|
122 |
|
|
cluster = memdesc->cluster;
|
123 |
|
|
for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
|
124 |
|
|
unsigned long tmp;
|
125 |
|
|
tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
|
126 |
|
|
if (tmp > high)
|
127 |
|
|
high = tmp;
|
128 |
|
|
}
|
129 |
|
|
/* round it up to an even number of pages.. */
|
130 |
|
|
high = (high + PAGE_SIZE) & (PAGE_MASK*2);
|
131 |
|
|
return PAGE_OFFSET + high;
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
void setup_arch(char **cmdline_p,
|
135 |
|
|
unsigned long * memory_start_p, unsigned long * memory_end_p)
|
136 |
|
|
{
|
137 |
|
|
extern int _end;
|
138 |
|
|
|
139 |
|
|
init_pit();
|
140 |
|
|
|
141 |
|
|
if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) {
|
142 |
|
|
#if 1
|
143 |
|
|
printk("init_timers: setting RTC_FREQ to 1024/sec\n");
|
144 |
|
|
#endif
|
145 |
|
|
CMOS_WRITE(0x26, RTC_FREQ_SELECT);
|
146 |
|
|
}
|
147 |
|
|
|
148 |
|
|
hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
|
149 |
|
|
|
150 |
|
|
#ifndef CONFIG_ALPHA_SRM_SETUP
|
151 |
|
|
set_hae(hae.cache); /* sync HAE register w/hae_cache */
|
152 |
|
|
#endif /* !SRM_SETUP */
|
153 |
|
|
|
154 |
|
|
wrmces(0x7); /* reset enable correctable error reports */
|
155 |
|
|
|
156 |
|
|
ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
|
157 |
|
|
command_line[COMMAND_LINE_SIZE - 1] = '\0';
|
158 |
|
|
|
159 |
|
|
/* Hack for Jensen... since we're restricted to 8 or 16
|
160 |
|
|
* chars for boot flags depending on the boot mode,
|
161 |
|
|
* we need some shorthand. This should do for
|
162 |
|
|
* installation. Later we'll add other abbreviations
|
163 |
|
|
* as well...
|
164 |
|
|
*/
|
165 |
|
|
if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
|
166 |
|
|
strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
|
167 |
|
|
strcpy(saved_command_line, command_line);
|
168 |
|
|
} else {
|
169 |
|
|
strcpy(command_line, COMMAND_LINE);
|
170 |
|
|
strcpy(saved_command_line, COMMAND_LINE);
|
171 |
|
|
}
|
172 |
|
|
printk("Command line: %s\n", command_line);
|
173 |
|
|
|
174 |
|
|
*cmdline_p = command_line;
|
175 |
|
|
*memory_start_p = (unsigned long) &_end;
|
176 |
|
|
*memory_end_p = find_end_memory();
|
177 |
|
|
|
178 |
|
|
#if defined(CONFIG_ALPHA_LCA)
|
179 |
|
|
*memory_start_p = lca_init(*memory_start_p, *memory_end_p);
|
180 |
|
|
#elif defined(CONFIG_ALPHA_APECS)
|
181 |
|
|
*memory_start_p = apecs_init(*memory_start_p, *memory_end_p);
|
182 |
|
|
#elif defined(CONFIG_ALPHA_CIA)
|
183 |
|
|
*memory_start_p = cia_init(*memory_start_p, *memory_end_p);
|
184 |
|
|
#elif defined(CONFIG_ALPHA_PYXIS)
|
185 |
|
|
*memory_start_p = pyxis_init(*memory_start_p, *memory_end_p);
|
186 |
|
|
#elif defined(CONFIG_ALPHA_T2)
|
187 |
|
|
*memory_start_p = t2_init(*memory_start_p, *memory_end_p);
|
188 |
|
|
#endif
|
189 |
|
|
}
|
190 |
|
|
|
191 |
|
|
# define N(a) (sizeof(a)/sizeof(a[0]))
|
192 |
|
|
|
193 |
|
|
/* A change was made to the HWRPB via an ECO and the following code tracks
|
194 |
|
|
* a part of the ECO. The HWRPB version must be 5 or higher or the ECO
|
195 |
|
|
* was not implemented in the console firmware. If its at rev 5 or greater
|
196 |
|
|
* we can get the platform ascii string name from the HWRPB. Thats what this
|
197 |
|
|
* function does. It checks the rev level and if the string is in the HWRPB
|
198 |
|
|
* it returns the addtess of the string ... a pointer to the platform name.
|
199 |
|
|
*
|
200 |
|
|
* Returns:
|
201 |
|
|
* - Pointer to a ascii string if its in the HWRPB
|
202 |
|
|
* - Pointer to a blank string if the data is not in the HWRPB.
|
203 |
|
|
*/
|
204 |
|
|
static char *
|
205 |
|
|
platform_string(void)
|
206 |
|
|
{
|
207 |
|
|
struct dsr_struct *dsr;
|
208 |
|
|
static char unk_system_string[] = "N/A";
|
209 |
|
|
|
210 |
|
|
/* Go to the console for the string pointer.
|
211 |
|
|
* If the rpb_vers is not 5 or greater the rpb
|
212 |
|
|
* is old and does not have this data in it.
|
213 |
|
|
*/
|
214 |
|
|
if (hwrpb->revision < 5)
|
215 |
|
|
return (unk_system_string);
|
216 |
|
|
else {
|
217 |
|
|
/* The Dynamic System Recognition struct
|
218 |
|
|
* has the system platform name starting
|
219 |
|
|
* after the character count of the string.
|
220 |
|
|
*/
|
221 |
|
|
dsr = ((struct dsr_struct *)
|
222 |
|
|
((char *)hwrpb + hwrpb->dsr_offset));
|
223 |
|
|
return ((char *)dsr + (dsr->sysname_off +
|
224 |
|
|
sizeof(long)));
|
225 |
|
|
}
|
226 |
|
|
}
|
227 |
|
|
|
228 |
|
|
static void
|
229 |
|
|
get_sysnames(long type, long variation,
|
230 |
|
|
char **type_name, char **variation_name)
|
231 |
|
|
{
|
232 |
|
|
static char *sys_unknown = "Unknown";
|
233 |
|
|
static char *systype_names[] = {
|
234 |
|
|
"0",
|
235 |
|
|
"ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
|
236 |
|
|
"Pelican", "Morgan", "Sable", "Medulla", "Noname",
|
237 |
|
|
"Turbolaser", "Avanti", "14", "Alcor", "Tradewind",
|
238 |
|
|
"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
|
239 |
|
|
"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
|
240 |
|
|
"Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
|
241 |
|
|
"Tsunami", "Wildfire", "CUSCO"
|
242 |
|
|
};
|
243 |
|
|
|
244 |
|
|
static char *unofficial_names[] = {
|
245 |
|
|
"100",
|
246 |
|
|
"Ruffian"
|
247 |
|
|
};
|
248 |
|
|
|
249 |
|
|
static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"};
|
250 |
|
|
static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
|
251 |
|
|
|
252 |
|
|
static char * alcor_names[] = {"Alcor", "Maverick", "Bret"};
|
253 |
|
|
static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
|
254 |
|
|
|
255 |
|
|
static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"};
|
256 |
|
|
static int eb64p_indices[] = {0,0,1.2};
|
257 |
|
|
|
258 |
|
|
static char * eb66_names[] = {"EB66", "EB66+"};
|
259 |
|
|
static int eb66_indices[] = {0,0,1};
|
260 |
|
|
|
261 |
|
|
static char * rawhide_names[] = {"Dodge", "Wrangler", "Durango",
|
262 |
|
|
"Tincup", "DaVinci"};
|
263 |
|
|
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
|
264 |
|
|
|
265 |
|
|
long member;
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
/* restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
|
269 |
|
|
if (type < 0) type = -type;
|
270 |
|
|
|
271 |
|
|
/* if not in the tables, make it UNKNOWN */
|
272 |
|
|
/* else set type name to family */
|
273 |
|
|
if (type < N(systype_names)) {
|
274 |
|
|
*type_name = systype_names[type];
|
275 |
|
|
} else
|
276 |
|
|
if ((type > ST_UNOFFICIAL_BIAS) &&
|
277 |
|
|
(type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
|
278 |
|
|
*type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
|
279 |
|
|
} else {
|
280 |
|
|
*type_name = sys_unknown;
|
281 |
|
|
*variation_name = sys_unknown;
|
282 |
|
|
return;
|
283 |
|
|
}
|
284 |
|
|
|
285 |
|
|
/* set variation to "0"; if variation is zero, done */
|
286 |
|
|
*variation_name = systype_names[0];
|
287 |
|
|
if (variation == 0) {
|
288 |
|
|
return;
|
289 |
|
|
}
|
290 |
|
|
|
291 |
|
|
member = (variation >> 10) & 0x3f; /* member ID is a bit-field */
|
292 |
|
|
|
293 |
|
|
switch (type) { /* select by family */
|
294 |
|
|
default: /* default to variation "0" ????FIXME???? */
|
295 |
|
|
break;
|
296 |
|
|
case ST_DEC_EB164:
|
297 |
|
|
if (member < N(eb164_indices))
|
298 |
|
|
*variation_name = eb164_names[eb164_indices[member]];
|
299 |
|
|
break;
|
300 |
|
|
case ST_DEC_ALCOR:
|
301 |
|
|
if (member < N(alcor_indices))
|
302 |
|
|
*variation_name = alcor_names[alcor_indices[member]];
|
303 |
|
|
break;
|
304 |
|
|
case ST_DEC_EB64P:
|
305 |
|
|
if (member < N(eb64p_indices))
|
306 |
|
|
*variation_name = eb64p_names[eb64p_indices[member]];
|
307 |
|
|
break;
|
308 |
|
|
case ST_DEC_EB66:
|
309 |
|
|
if (member < N(eb66_indices))
|
310 |
|
|
*variation_name = eb66_names[eb66_indices[member]];
|
311 |
|
|
break;
|
312 |
|
|
case ST_DEC_RAWHIDE:
|
313 |
|
|
if (member < N(rawhide_indices))
|
314 |
|
|
*variation_name = rawhide_names[rawhide_indices[member]];
|
315 |
|
|
break;
|
316 |
|
|
} /* end family switch */
|
317 |
|
|
return;
|
318 |
|
|
}
|
319 |
|
|
|
320 |
|
|
int get_cpuinfo(char *buffer)
|
321 |
|
|
/* BUFFER is PAGE_SIZE bytes long. */
|
322 |
|
|
{
|
323 |
|
|
const char *cpu_name[] = {
|
324 |
|
|
"EV3", "EV4", "Unknown 1", "LCA4", "EV5", "EV45", "EV56",
|
325 |
|
|
"EV6", "PCA56"
|
326 |
|
|
};
|
327 |
|
|
struct percpu_struct *cpu;
|
328 |
|
|
unsigned int cpu_index;
|
329 |
|
|
char *systype_name;
|
330 |
|
|
char *sysvariation_name;
|
331 |
|
|
extern struct unaligned_stat {
|
332 |
|
|
unsigned long count, va, pc;
|
333 |
|
|
} unaligned[2];
|
334 |
|
|
|
335 |
|
|
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
|
336 |
|
|
cpu_index = (unsigned) (cpu->type - 1);
|
337 |
|
|
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
|
338 |
|
|
&systype_name, &sysvariation_name);
|
339 |
|
|
|
340 |
|
|
return sprintf(buffer,
|
341 |
|
|
"cpu\t\t\t: Alpha\n"
|
342 |
|
|
"cpu model\t\t: %s\n"
|
343 |
|
|
"cpu variation\t\t: %ld\n"
|
344 |
|
|
"cpu revision\t\t: %ld\n"
|
345 |
|
|
"cpu serial number\t: %s\n"
|
346 |
|
|
"system type\t\t: %s\n"
|
347 |
|
|
"system variation\t: %s\n"
|
348 |
|
|
"system revision\t\t: %ld\n"
|
349 |
|
|
"system serial number\t: %s\n"
|
350 |
|
|
"cycle frequency [Hz]\t: %lu\n"
|
351 |
|
|
"timer frequency [Hz]\t: %lu.%02lu\n"
|
352 |
|
|
"page size [bytes]\t: %ld\n"
|
353 |
|
|
"phys. address bits\t: %ld\n"
|
354 |
|
|
"max. addr. space #\t: %ld\n"
|
355 |
|
|
"BogoMIPS\t\t: %lu.%02lu\n"
|
356 |
|
|
"kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
|
357 |
|
|
"user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
|
358 |
|
|
"platform string\t\t: %s\n",
|
359 |
|
|
|
360 |
|
|
(cpu_index < N(cpu_name)
|
361 |
|
|
? cpu_name[cpu_index] : "Unknown"),
|
362 |
|
|
cpu->variation, cpu->revision, (char*)cpu->serial_no,
|
363 |
|
|
systype_name, sysvariation_name, hwrpb->sys_revision,
|
364 |
|
|
(char*)hwrpb->ssn,
|
365 |
|
|
hwrpb->cycle_freq,
|
366 |
|
|
hwrpb->intr_freq / 4096,
|
367 |
|
|
(100 * hwrpb->intr_freq / 4096) % 100,
|
368 |
|
|
hwrpb->pagesize,
|
369 |
|
|
hwrpb->pa_bits,
|
370 |
|
|
hwrpb->max_asn,
|
371 |
|
|
loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
|
372 |
|
|
unaligned[0].count, unaligned[0].pc, unaligned[0].va,
|
373 |
|
|
unaligned[1].count, unaligned[1].pc, unaligned[1].va,
|
374 |
|
|
platform_string());
|
375 |
|
|
}
|
376 |
|
|
# undef N
|