File: /usr/src/linux/arch/m68k/kernel/setup.c

1     /*
2      *  linux/arch/m68k/kernel/setup.c
3      *
4      *  Copyright (C) 1995  Hamish Macdonald
5      */
6     
7     /*
8      * This file handles the architecture-dependent parts of system setup
9      */
10     
11     #include <linux/config.h>
12     #include <linux/kernel.h>
13     #include <linux/mm.h>
14     #include <linux/sched.h>
15     #include <linux/delay.h>
16     #include <linux/interrupt.h>
17     #include <linux/fs.h>
18     #include <linux/console.h>
19     #include <linux/genhd.h>
20     #include <linux/errno.h>
21     #include <linux/string.h>
22     #include <linux/init.h>
23     #include <linux/bootmem.h>
24     #include <linux/module.h>
25     
26     #include <asm/bootinfo.h>
27     #include <asm/setup.h>
28     #include <asm/irq.h>
29     #include <asm/io.h>
30     #include <asm/machdep.h>
31     #ifdef CONFIG_AMIGA
32     #include <asm/amigahw.h>
33     #endif
34     #ifdef CONFIG_ATARI
35     #include <asm/atarihw.h>
36     #endif
37     #ifdef CONFIG_SUN3X
38     #include <asm/dvma.h>
39     extern void sun_serial_setup(void);
40     #endif
41     
42     #ifdef CONFIG_BLK_DEV_INITRD
43     #include <linux/blk.h>
44     #endif
45     
46     unsigned long m68k_machtype;
47     unsigned long m68k_cputype;
48     unsigned long m68k_fputype;
49     unsigned long m68k_mmutype;
50     #ifdef CONFIG_VME
51     unsigned long vme_brdtype;
52     #endif
53     
54     int m68k_is040or060 = 0;
55     
56     extern int end;
57     extern unsigned long availmem;
58     
59     int m68k_num_memory = 0;
60     int m68k_realnum_memory = 0;
61     unsigned long m68k_memoffset;
62     struct mem_info m68k_memory[NUM_MEMINFO];
63     
64     static struct mem_info m68k_ramdisk = { 0, 0 };
65     
66     static char m68k_command_line[CL_SIZE];
67     char saved_command_line[CL_SIZE];
68     
69     char m68k_debug_device[6] = "";
70     
71     void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
72     /* machine dependent keyboard functions */
73     int (*mach_keyb_init) (void) __initdata = NULL;
74     int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
75     void (*mach_kbd_leds) (unsigned int) = NULL;
76     int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL;
77     unsigned int SYSRQ_KEY;
78     /* machine dependent irq functions */
79     void (*mach_init_IRQ) (void) __initdata = NULL;
80     void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
81     void (*mach_get_model) (char *model) = NULL;
82     int (*mach_get_hardware_list) (char *buffer) = NULL;
83     int (*mach_get_irq_list) (char *) = NULL;
84     void (*mach_process_int) (int, struct pt_regs *) = NULL;
85     /* machine dependent timer functions */
86     unsigned long (*mach_gettimeoffset) (void);
87     void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
88     int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
89     int (*mach_set_clock_mmss) (unsigned long) = NULL;
90     void (*mach_reset)( void );
91     void (*mach_halt)( void ) = NULL;
92     void (*mach_power_off)( void ) = NULL;
93     long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
94     #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) 
95     void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
96     void (*mach_floppy_eject) (void) = NULL;
97     #endif
98     #ifdef CONFIG_HEARTBEAT
99     void (*mach_heartbeat) (int) = NULL;
100     EXPORT_SYMBOL(mach_heartbeat);
101     #endif
102     #ifdef CONFIG_M68K_L2_CACHE
103     void (*mach_l2_flush) (int) = NULL;
104     #endif
105     
106     #ifdef CONFIG_MAGIC_SYSRQ
107     int mach_sysrq_key = -1;
108     int mach_sysrq_shift_state = 0;
109     int mach_sysrq_shift_mask = 0;
110     char *mach_sysrq_xlate = NULL;
111     #endif
112     
113     #if defined(CONFIG_ISA)
114     int isa_type;
115     int isa_sex;
116     #endif
117     
118     extern int amiga_parse_bootinfo(const struct bi_record *);
119     extern int atari_parse_bootinfo(const struct bi_record *);
120     extern int mac_parse_bootinfo(const struct bi_record *);
121     extern int q40_parse_bootinfo(const struct bi_record *);
122     extern int bvme6000_parse_bootinfo(const struct bi_record *);
123     extern int mvme16x_parse_bootinfo(const struct bi_record *);
124     extern int mvme147_parse_bootinfo(const struct bi_record *);
125     
126     extern void config_amiga(void);
127     extern void config_atari(void);
128     extern void config_mac(void);
129     extern void config_sun3(void);
130     extern void config_apollo(void);
131     extern void config_mvme147(void);
132     extern void config_mvme16x(void);
133     extern void config_bvme6000(void);
134     extern void config_hp300(void);
135     extern void config_q40(void);
136     extern void config_sun3x(void);
137     
138     extern void mac_debugging_short (int, short);
139     extern void mac_debugging_long  (int, long);
140     
141     #define MASK_256K 0xfffc0000
142     
143     extern void paging_init(void);
144     
145     static void __init m68k_parse_bootinfo(const struct bi_record *record)
146     {
147         while (record->tag != BI_LAST) {
148     	int unknown = 0;
149     	const unsigned long *data = record->data;
150     	switch (record->tag) {
151     	    case BI_MACHTYPE:
152     	    case BI_CPUTYPE:
153     	    case BI_FPUTYPE:
154     	    case BI_MMUTYPE:
155     		/* Already set up by head.S */
156     		break;
157     
158      	    case BI_MEMCHUNK:
159     		if (m68k_num_memory < NUM_MEMINFO) {
160     		    m68k_memory[m68k_num_memory].addr = data[0];
161     		    m68k_memory[m68k_num_memory].size = data[1];
162     		    m68k_num_memory++;
163     		} else
164     		    printk("m68k_parse_bootinfo: too many memory chunks\n");
165     		break;
166     
167     	    case BI_RAMDISK:
168     		m68k_ramdisk.addr = data[0];
169     		m68k_ramdisk.size = data[1];
170     		break;
171     
172     	    case BI_COMMAND_LINE:
173     		strncpy(m68k_command_line, (const char *)data, CL_SIZE);
174     		m68k_command_line[CL_SIZE-1] = '\0';
175     		break;
176     
177     	    default:
178     		if (MACH_IS_AMIGA)
179     		    unknown = amiga_parse_bootinfo(record);
180     		else if (MACH_IS_ATARI)
181     		    unknown = atari_parse_bootinfo(record);
182     		else if (MACH_IS_MAC)
183     		    unknown = mac_parse_bootinfo(record);
184     		else if (MACH_IS_Q40)
185     		    unknown = q40_parse_bootinfo(record);
186     		else if (MACH_IS_BVME6000)
187     		    unknown = bvme6000_parse_bootinfo(record);
188     		else if (MACH_IS_MVME16x)
189     		    unknown = mvme16x_parse_bootinfo(record);
190     		else if (MACH_IS_MVME147)
191     		    unknown = mvme147_parse_bootinfo(record);
192     		else
193     		    unknown = 1;
194     	}
195     	if (unknown)
196     	    printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
197     		   record->tag);
198     	record = (struct bi_record *)((unsigned long)record+record->size);
199         }
200     
201         m68k_realnum_memory = m68k_num_memory;
202     #ifdef CONFIG_SINGLE_MEMORY_CHUNK
203         if (m68k_num_memory > 1) {
204     	printk("Ignoring last %i chunks of physical memory\n",
205     	       (m68k_num_memory - 1));
206     	m68k_num_memory = 1;
207         }
208         m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
209     #endif
210     }
211     
212     void __init setup_arch(char **cmdline_p)
213     {
214     	extern int _etext, _edata, _end;
215     #ifndef CONFIG_SUN3
216     	unsigned long endmem, startmem;
217     #endif
218     	int i;
219     	char *p, *q;
220     
221     	/* The bootinfo is located right after the kernel bss */
222     	m68k_parse_bootinfo((const struct bi_record *)&_end);
223     
224     	if (CPU_IS_040)
225     		m68k_is040or060 = 4;
226     	else if (CPU_IS_060)
227     		m68k_is040or060 = 6;
228     
229     	/* FIXME: m68k_fputype is passed in by Penguin booter, which can
230     	 * be confused by software FPU emulation. BEWARE.
231     	 * We should really do our own FPU check at startup.
232     	 * [what do we do with buggy 68LC040s? if we have problems
233     	 *  with them, we should add a test to check_bugs() below] */
234     #ifndef CONFIG_M68KFPU_EMU_ONLY
235     	/* clear the fpu if we have one */
236     	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
237     		volatile int zero = 0;
238     		asm __volatile__ ("frestore %0" : : "m" (zero));
239     	}
240     #endif	
241     
242     	init_mm.start_code = PAGE_OFFSET;
243     	init_mm.end_code = (unsigned long) &_etext;
244     	init_mm.end_data = (unsigned long) &_edata;
245     	init_mm.brk = (unsigned long) &_end;
246     
247     	*cmdline_p = m68k_command_line;
248     	memcpy(saved_command_line, *cmdline_p, CL_SIZE);
249     
250     	/* Parse the command line for arch-specific options.
251     	 * For the m68k, this is currently only "debug=xxx" to enable printing
252     	 * certain kernel messages to some machine-specific device.
253     	 */
254     	for( p = *cmdline_p; p && *p; ) {
255     	    i = 0;
256     	    if (!strncmp( p, "debug=", 6 )) {
257     		strncpy( m68k_debug_device, p+6, sizeof(m68k_debug_device)-1 );
258     		m68k_debug_device[sizeof(m68k_debug_device)-1] = 0;
259     		if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
260     		i = 1;
261     	    }
262     #ifdef CONFIG_ATARI
263     	    /* This option must be parsed very early */
264     	    if (!strncmp( p, "switches=", 9 )) {
265     		extern void atari_switches_setup( const char *, int );
266     		atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
267     				           (q - (p+9)) : strlen(p+9) );
268     		i = 1;
269     	    }
270     #endif
271     
272     	    if (i) {
273     		/* option processed, delete it */
274     		if ((q = strchr( p, ' ' )))
275     		    strcpy( p, q+1 );
276     		else
277     		    *p = 0;
278     	    } else {
279     		if ((p = strchr( p, ' ' ))) ++p;
280     	    }
281     	}
282     
283     	switch (m68k_machtype) {
284     #ifdef CONFIG_AMIGA
285     	    case MACH_AMIGA:
286     		config_amiga();
287     		break;
288     #endif
289     #ifdef CONFIG_ATARI
290     	    case MACH_ATARI:
291     		config_atari();
292     		break;
293     #endif
294     #ifdef CONFIG_MAC
295     	    case MACH_MAC:
296     		config_mac();
297     		break;
298     #endif
299     #ifdef CONFIG_SUN3
300     	    case MACH_SUN3:
301     	    	config_sun3();
302     	    	break;
303     #endif
304     #ifdef CONFIG_APOLLO
305     	    case MACH_APOLLO:
306     	    	config_apollo();
307     	    	break;
308     #endif
309     #ifdef CONFIG_MVME147
310     	    case MACH_MVME147:
311     	    	config_mvme147();
312     	    	break;
313     #endif
314     #ifdef CONFIG_MVME16x
315     	    case MACH_MVME16x:
316     	    	config_mvme16x();
317     	    	break;
318     #endif
319     #ifdef CONFIG_BVME6000
320     	    case MACH_BVME6000:
321     	    	config_bvme6000();
322     	    	break;
323     #endif
324     #ifdef CONFIG_HP300
325     	    case MACH_HP300:
326     		config_hp300();
327     		break;
328     #endif
329     #ifdef CONFIG_Q40
330     	    case MACH_Q40:
331     	        config_q40();
332     		break;
333     #endif
334     #ifdef CONFIG_SUN3X
335     	    case MACH_SUN3X:
336     		config_sun3x();
337     		break;
338     #endif
339     	    default:
340     		panic ("No configuration setup");
341     	}
342     
343     #ifndef CONFIG_SUN3
344     	startmem= m68k_memory[0].addr;
345     	endmem = startmem + m68k_memory[0].size;
346     	high_memory = PAGE_OFFSET;
347     	for (i = 0; i < m68k_num_memory; i++) {
348     		m68k_memory[i].size &= MASK_256K;
349     		if (m68k_memory[i].addr < startmem)
350     			startmem = m68k_memory[i].addr;
351     		if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
352     			endmem = m68k_memory[i].addr+m68k_memory[i].size;
353     		high_memory += m68k_memory[i].size;
354     	}
355     
356     	availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
357     				      startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
358     
359     	for (i = 0; i < m68k_num_memory; i++)
360     		free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
361     
362     	reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
363     
364     #ifdef CONFIG_BLK_DEV_INITRD
365     	if (m68k_ramdisk.size) {
366     		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
367     		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
368     		initrd_end = initrd_start + m68k_ramdisk.size;
369     		printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
370     	}
371     #endif
372     
373     #ifdef CONFIG_ATARI
374     	if (MACH_IS_ATARI)
375     		atari_stram_reserve_pages(availmem);
376     #endif
377     #ifdef CONFIG_SUN3X
378     	if (MACH_IS_SUN3X) {
379     		dvma_init();
380     #ifdef CONFIG_SUN3X_ZS
381     		sun_serial_setup();
382     #endif
383     	}
384     #endif
385     
386     #endif /* !CONFIG_SUN3 */
387     
388     	paging_init();
389     
390     /* set ISA defs early as possible */
391     #if defined(CONFIG_ISA)
392     #if defined(CONFIG_Q40) 
393     	if (MACH_IS_Q40) {
394     	    isa_type = Q40_ISA;
395     	    isa_sex = 0;
396     	} 
397     #elif defined(CONFIG_GG2)
398     	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
399     	    isa_type = GG2_ISA;
400     	    isa_sex = 0;
401     	}
402     #elif defined(CONFIG_AMIGA_PCMCIA)
403     	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
404     	    isa_type = AG_ISA;
405     	    isa_sex = 1;
406     	}
407     #endif
408     #endif
409     }
410     
411     int get_cpuinfo(char * buffer)
412     {
413         const char *cpu, *mmu, *fpu;
414         unsigned long clockfreq, clockfactor;
415     
416     #define LOOP_CYCLES_68020	(8)
417     #define LOOP_CYCLES_68030	(8)
418     #define LOOP_CYCLES_68040	(3)
419     #define LOOP_CYCLES_68060	(1)
420     
421         if (CPU_IS_020) {
422     	cpu = "68020";
423     	clockfactor = LOOP_CYCLES_68020;
424         } else if (CPU_IS_030) {
425     	cpu = "68030";
426     	clockfactor = LOOP_CYCLES_68030;
427         } else if (CPU_IS_040) {
428     	cpu = "68040";
429     	clockfactor = LOOP_CYCLES_68040;
430         } else if (CPU_IS_060) {
431     	cpu = "68060";
432     	clockfactor = LOOP_CYCLES_68060;
433         } else {
434     	cpu = "680x0";
435     	clockfactor = 0;
436         }
437     
438     #ifdef CONFIG_M68KFPU_EMU_ONLY
439         fpu="none(soft float)";
440     #else
441         if (m68k_fputype & FPU_68881)
442     	fpu = "68881";
443         else if (m68k_fputype & FPU_68882)
444     	fpu = "68882";
445         else if (m68k_fputype & FPU_68040)
446     	fpu = "68040";
447         else if (m68k_fputype & FPU_68060)
448     	fpu = "68060";
449         else if (m68k_fputype & FPU_SUNFPA)
450     	fpu = "Sun FPA";
451         else
452     	fpu = "none";
453     #endif
454     
455         if (m68k_mmutype & MMU_68851)
456     	mmu = "68851";
457         else if (m68k_mmutype & MMU_68030)
458     	mmu = "68030";
459         else if (m68k_mmutype & MMU_68040)
460     	mmu = "68040";
461         else if (m68k_mmutype & MMU_68060)
462     	mmu = "68060";
463         else if (m68k_mmutype & MMU_SUN3)
464     	mmu = "Sun-3";
465         else if (m68k_mmutype & MMU_APOLLO)
466     	mmu = "Apollo";
467         else
468     	mmu = "unknown";
469     
470         clockfreq = loops_per_jiffy*HZ*clockfactor;
471     
472         return(sprintf(buffer, "CPU:\t\t%s\n"
473     		   "MMU:\t\t%s\n"
474     		   "FPU:\t\t%s\n"
475     		   "Clocking:\t%lu.%1luMHz\n"
476     		   "BogoMips:\t%lu.%02lu\n"
477     		   "Calibration:\t%lu loops\n",
478     		   cpu, mmu, fpu,
479     		   clockfreq/1000000,(clockfreq/100000)%10,
480     		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
481     		   loops_per_jiffy));
482     
483     }
484     
485     int get_hardware_list(char *buffer)
486     {
487         int len = 0;
488         char model[80];
489         unsigned long mem;
490         int i;
491     
492         if (mach_get_model)
493     	mach_get_model(model);
494         else
495     	strcpy(model, "Unknown m68k");
496     
497         len += sprintf(buffer+len, "Model:\t\t%s\n", model);
498         len += get_cpuinfo(buffer+len);
499         for (mem = 0, i = 0; i < m68k_num_memory; i++)
500     	mem += m68k_memory[i].size;
501         len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
502     
503         if (mach_get_hardware_list)
504     	len += mach_get_hardware_list(buffer+len);
505     
506         return(len);
507     }
508     
509     
510     #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
511     void __init floppy_setup(char *str, int *ints)
512     {
513     	if (mach_floppy_setup)
514     		mach_floppy_setup (str, ints);
515     }
516     
517     void floppy_eject(void)
518     {
519     	if (mach_floppy_eject)
520     		mach_floppy_eject();
521     }
522     #endif
523     
524     /* for "kbd-reset" cmdline param */
525     void __init kbd_reset_setup(char *str, int *ints)
526     {
527     }
528     
529     void arch_gettod(int *year, int *mon, int *day, int *hour,
530     		 int *min, int *sec)
531     {
532     	if (mach_gettod)
533     		mach_gettod(year, mon, day, hour, min, sec);
534     	else
535     		*year = *mon = *day = *hour = *min = *sec = 0;
536     }
537     
538     void check_bugs(void)
539     {
540     #ifndef CONFIG_M68KFPU_EMU
541     	if (m68k_fputype == 0) {
542     		printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
543     				"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
544     		printk( KERN_EMERG "Upgrade your hardware or join the FPU "
545     				"emulation project\n" );
546     		printk( KERN_EMERG "(see http://no-fpu.linux-m68k.org)\n" );
547     		panic( "no FPU" );
548     	}
549     
550     #endif /* CONFIG_SUN3 */
551     
552     }
553