diff options
Diffstat (limited to 'arch/m68k/atari/config.c')
-rw-r--r-- | arch/m68k/atari/config.c | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c new file mode 100644 index 000000000000..9261d2deeaf5 --- /dev/null +++ b/arch/m68k/atari/config.c | |||
@@ -0,0 +1,726 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/atari/config.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Bjoern Brauel | ||
5 | * | ||
6 | * 5/2/94 Roman Hodek: | ||
7 | * Added setting of time_adj to get a better clock. | ||
8 | * | ||
9 | * 5/14/94 Roman Hodek: | ||
10 | * gettod() for TT | ||
11 | * | ||
12 | * 5/15/94 Roman Hodek: | ||
13 | * hard_reset_now() for Atari (and others?) | ||
14 | * | ||
15 | * 94/12/30 Andreas Schwab: | ||
16 | * atari_sched_init fixed to get precise clock. | ||
17 | * | ||
18 | * This file is subject to the terms and conditions of the GNU General Public | ||
19 | * License. See the file COPYING in the main directory of this archive | ||
20 | * for more details. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * Miscellaneous atari stuff | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/console.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/ioport.h> | ||
34 | #include <linux/vt_kern.h> | ||
35 | |||
36 | #include <asm/bootinfo.h> | ||
37 | #include <asm/setup.h> | ||
38 | #include <asm/atarihw.h> | ||
39 | #include <asm/atariints.h> | ||
40 | #include <asm/atari_stram.h> | ||
41 | #include <asm/system.h> | ||
42 | #include <asm/machdep.h> | ||
43 | #include <asm/hwtest.h> | ||
44 | #include <asm/io.h> | ||
45 | |||
46 | u_long atari_mch_cookie; | ||
47 | u_long atari_mch_type; | ||
48 | struct atari_hw_present atari_hw_present; | ||
49 | u_long atari_switches; | ||
50 | int atari_dont_touch_floppy_select; | ||
51 | int atari_rtc_year_offset; | ||
52 | |||
53 | /* local function prototypes */ | ||
54 | static void atari_reset( void ); | ||
55 | #ifdef CONFIG_ATARI_FLOPPY | ||
56 | extern void atari_floppy_setup(char *, int *); | ||
57 | #endif | ||
58 | static void atari_get_model(char *model); | ||
59 | static int atari_get_hardware_list(char *buffer); | ||
60 | |||
61 | /* atari specific irq functions */ | ||
62 | extern void atari_init_IRQ (void); | ||
63 | extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
64 | unsigned long flags, const char *devname, void *dev_id); | ||
65 | extern void atari_free_irq (unsigned int irq, void *dev_id); | ||
66 | extern void atari_enable_irq (unsigned int); | ||
67 | extern void atari_disable_irq (unsigned int); | ||
68 | extern int show_atari_interrupts (struct seq_file *, void *); | ||
69 | extern void atari_mksound( unsigned int count, unsigned int ticks ); | ||
70 | #ifdef CONFIG_HEARTBEAT | ||
71 | static void atari_heartbeat( int on ); | ||
72 | #endif | ||
73 | |||
74 | /* atari specific timer functions (in time.c) */ | ||
75 | extern void atari_sched_init(irqreturn_t (*)(int, void *, struct pt_regs *)); | ||
76 | extern unsigned long atari_gettimeoffset (void); | ||
77 | extern int atari_mste_hwclk (int, struct rtc_time *); | ||
78 | extern int atari_tt_hwclk (int, struct rtc_time *); | ||
79 | extern int atari_mste_set_clock_mmss (unsigned long); | ||
80 | extern int atari_tt_set_clock_mmss (unsigned long); | ||
81 | |||
82 | /* atari specific debug functions (in debug.c) */ | ||
83 | extern void atari_debug_init(void); | ||
84 | |||
85 | |||
86 | /* I've moved hwreg_present() and hwreg_present_bywrite() out into | ||
87 | * mm/hwtest.c, to avoid having multiple copies of the same routine | ||
88 | * in the kernel [I wanted them in hp300 and they were already used | ||
89 | * in the nubus code. NB: I don't have an Atari so this might (just | ||
90 | * conceivably) break something. | ||
91 | * I've preserved the #if 0 version of hwreg_present_bywrite() here | ||
92 | * for posterity. | ||
93 | * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998 | ||
94 | */ | ||
95 | |||
96 | #if 0 | ||
97 | static int __init | ||
98 | hwreg_present_bywrite(volatile void *regp, unsigned char val) | ||
99 | { | ||
100 | int ret; | ||
101 | long save_sp, save_vbr; | ||
102 | static long tmp_vectors[3] = { [2] = (long)&&after_test }; | ||
103 | |||
104 | __asm__ __volatile__ | ||
105 | ( "movec %/vbr,%2\n\t" /* save vbr value */ | ||
106 | "movec %4,%/vbr\n\t" /* set up temporary vectors */ | ||
107 | "movel %/sp,%1\n\t" /* save sp */ | ||
108 | "moveq #0,%0\n\t" /* assume not present */ | ||
109 | "moveb %5,%3@\n\t" /* write the hardware reg */ | ||
110 | "cmpb %3@,%5\n\t" /* compare it */ | ||
111 | "seq %0" /* comes here only if reg */ | ||
112 | /* is present */ | ||
113 | : "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr) | ||
114 | : "a" (regp), "r" (tmp_vectors), "d" (val) | ||
115 | ); | ||
116 | after_test: | ||
117 | __asm__ __volatile__ | ||
118 | ( "movel %0,%/sp\n\t" /* restore sp */ | ||
119 | "movec %1,%/vbr" /* restore vbr */ | ||
120 | : : "r" (save_sp), "r" (save_vbr) : "sp" | ||
121 | ); | ||
122 | |||
123 | return( ret ); | ||
124 | } | ||
125 | #endif | ||
126 | |||
127 | |||
128 | /* ++roman: This is a more elaborate test for an SCC chip, since the plain | ||
129 | * Medusa board generates DTACK at the SCC's standard addresses, but a SCC | ||
130 | * board in the Medusa is possible. Also, the addresses where the ST_ESCC | ||
131 | * resides generate DTACK without the chip, too. | ||
132 | * The method is to write values into the interrupt vector register, that | ||
133 | * should be readable without trouble (from channel A!). | ||
134 | */ | ||
135 | |||
136 | static int __init scc_test( volatile char *ctla ) | ||
137 | { | ||
138 | if (!hwreg_present( ctla )) | ||
139 | return( 0 ); | ||
140 | MFPDELAY(); | ||
141 | |||
142 | *ctla = 2; MFPDELAY(); | ||
143 | *ctla = 0x40; MFPDELAY(); | ||
144 | |||
145 | *ctla = 2; MFPDELAY(); | ||
146 | if (*ctla != 0x40) return( 0 ); | ||
147 | MFPDELAY(); | ||
148 | |||
149 | *ctla = 2; MFPDELAY(); | ||
150 | *ctla = 0x60; MFPDELAY(); | ||
151 | |||
152 | *ctla = 2; MFPDELAY(); | ||
153 | if (*ctla != 0x60) return( 0 ); | ||
154 | |||
155 | return( 1 ); | ||
156 | } | ||
157 | |||
158 | |||
159 | /* | ||
160 | * Parse an Atari-specific record in the bootinfo | ||
161 | */ | ||
162 | |||
163 | int __init atari_parse_bootinfo(const struct bi_record *record) | ||
164 | { | ||
165 | int unknown = 0; | ||
166 | const u_long *data = record->data; | ||
167 | |||
168 | switch (record->tag) { | ||
169 | case BI_ATARI_MCH_COOKIE: | ||
170 | atari_mch_cookie = *data; | ||
171 | break; | ||
172 | case BI_ATARI_MCH_TYPE: | ||
173 | atari_mch_type = *data; | ||
174 | break; | ||
175 | default: | ||
176 | unknown = 1; | ||
177 | } | ||
178 | return(unknown); | ||
179 | } | ||
180 | |||
181 | |||
182 | /* Parse the Atari-specific switches= option. */ | ||
183 | void __init atari_switches_setup( const char *str, unsigned len ) | ||
184 | { | ||
185 | char switches[len+1]; | ||
186 | char *p; | ||
187 | int ovsc_shift; | ||
188 | char *args = switches; | ||
189 | |||
190 | /* copy string to local array, strsep works destructively... */ | ||
191 | strlcpy( switches, str, sizeof(switches) ); | ||
192 | atari_switches = 0; | ||
193 | |||
194 | /* parse the options */ | ||
195 | while ((p = strsep(&args, ",")) != NULL) { | ||
196 | if (!*p) continue; | ||
197 | ovsc_shift = 0; | ||
198 | if (strncmp( p, "ov_", 3 ) == 0) { | ||
199 | p += 3; | ||
200 | ovsc_shift = ATARI_SWITCH_OVSC_SHIFT; | ||
201 | } | ||
202 | |||
203 | if (strcmp( p, "ikbd" ) == 0) { | ||
204 | /* RTS line of IKBD ACIA */ | ||
205 | atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift; | ||
206 | } | ||
207 | else if (strcmp( p, "midi" ) == 0) { | ||
208 | /* RTS line of MIDI ACIA */ | ||
209 | atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift; | ||
210 | } | ||
211 | else if (strcmp( p, "snd6" ) == 0) { | ||
212 | atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift; | ||
213 | } | ||
214 | else if (strcmp( p, "snd7" ) == 0) { | ||
215 | atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | /* | ||
222 | * Setup the Atari configuration info | ||
223 | */ | ||
224 | |||
225 | void __init config_atari(void) | ||
226 | { | ||
227 | unsigned short tos_version; | ||
228 | |||
229 | memset(&atari_hw_present, 0, sizeof(atari_hw_present)); | ||
230 | |||
231 | atari_debug_init(); | ||
232 | |||
233 | ioport_resource.end = 0xFFFFFFFF; /* Change size of I/O space from 64KB | ||
234 | to 4GB. */ | ||
235 | |||
236 | mach_sched_init = atari_sched_init; | ||
237 | mach_init_IRQ = atari_init_IRQ; | ||
238 | mach_request_irq = atari_request_irq; | ||
239 | mach_free_irq = atari_free_irq; | ||
240 | enable_irq = atari_enable_irq; | ||
241 | disable_irq = atari_disable_irq; | ||
242 | mach_get_model = atari_get_model; | ||
243 | mach_get_hardware_list = atari_get_hardware_list; | ||
244 | mach_get_irq_list = show_atari_interrupts; | ||
245 | mach_gettimeoffset = atari_gettimeoffset; | ||
246 | mach_reset = atari_reset; | ||
247 | #ifdef CONFIG_ATARI_FLOPPY | ||
248 | mach_floppy_setup = atari_floppy_setup; | ||
249 | #endif | ||
250 | #ifdef CONFIG_DUMMY_CONSOLE | ||
251 | conswitchp = &dummy_con; | ||
252 | #endif | ||
253 | mach_max_dma_address = 0xffffff; | ||
254 | #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) | ||
255 | mach_beep = atari_mksound; | ||
256 | #endif | ||
257 | #ifdef CONFIG_HEARTBEAT | ||
258 | mach_heartbeat = atari_heartbeat; | ||
259 | #endif | ||
260 | |||
261 | /* Set switches as requested by the user */ | ||
262 | if (atari_switches & ATARI_SWITCH_IKBD) | ||
263 | acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID; | ||
264 | if (atari_switches & ATARI_SWITCH_MIDI) | ||
265 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; | ||
266 | if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) { | ||
267 | sound_ym.rd_data_reg_sel = 14; | ||
268 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | | ||
269 | ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) | | ||
270 | ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0); | ||
271 | } | ||
272 | |||
273 | /* ++bjoern: | ||
274 | * Determine hardware present | ||
275 | */ | ||
276 | |||
277 | printk( "Atari hardware found: " ); | ||
278 | if (MACH_IS_MEDUSA || MACH_IS_HADES) { | ||
279 | /* There's no Atari video hardware on the Medusa, but all the | ||
280 | * addresses below generate a DTACK so no bus error occurs! */ | ||
281 | } | ||
282 | else if (hwreg_present( f030_xreg )) { | ||
283 | ATARIHW_SET(VIDEL_SHIFTER); | ||
284 | printk( "VIDEL " ); | ||
285 | /* This is a temporary hack: If there is Falcon video | ||
286 | * hardware, we assume that the ST-DMA serves SCSI instead of | ||
287 | * ACSI. In the future, there should be a better method for | ||
288 | * this... | ||
289 | */ | ||
290 | ATARIHW_SET(ST_SCSI); | ||
291 | printk( "STDMA-SCSI " ); | ||
292 | } | ||
293 | else if (hwreg_present( tt_palette )) { | ||
294 | ATARIHW_SET(TT_SHIFTER); | ||
295 | printk( "TT_SHIFTER " ); | ||
296 | } | ||
297 | else if (hwreg_present( &shifter.bas_hi )) { | ||
298 | if (hwreg_present( &shifter.bas_lo ) && | ||
299 | (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) { | ||
300 | ATARIHW_SET(EXTD_SHIFTER); | ||
301 | printk( "EXTD_SHIFTER " ); | ||
302 | } | ||
303 | else { | ||
304 | ATARIHW_SET(STND_SHIFTER); | ||
305 | printk( "STND_SHIFTER " ); | ||
306 | } | ||
307 | } | ||
308 | if (hwreg_present( &mfp.par_dt_reg )) { | ||
309 | ATARIHW_SET(ST_MFP); | ||
310 | printk( "ST_MFP " ); | ||
311 | } | ||
312 | if (hwreg_present( &tt_mfp.par_dt_reg )) { | ||
313 | ATARIHW_SET(TT_MFP); | ||
314 | printk( "TT_MFP " ); | ||
315 | } | ||
316 | if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) { | ||
317 | ATARIHW_SET(SCSI_DMA); | ||
318 | printk( "TT_SCSI_DMA " ); | ||
319 | } | ||
320 | if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) { | ||
321 | ATARIHW_SET(STND_DMA); | ||
322 | printk( "STND_DMA " ); | ||
323 | } | ||
324 | if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable | ||
325 | * on all Medusas, so the test below may fail */ | ||
326 | (hwreg_present( &st_dma.dma_vhi ) && | ||
327 | (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) && | ||
328 | st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa && | ||
329 | (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) && | ||
330 | st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) { | ||
331 | ATARIHW_SET(EXTD_DMA); | ||
332 | printk( "EXTD_DMA " ); | ||
333 | } | ||
334 | if (hwreg_present( &tt_scsi.scsi_data )) { | ||
335 | ATARIHW_SET(TT_SCSI); | ||
336 | printk( "TT_SCSI " ); | ||
337 | } | ||
338 | if (hwreg_present( &sound_ym.rd_data_reg_sel )) { | ||
339 | ATARIHW_SET(YM_2149); | ||
340 | printk( "YM2149 " ); | ||
341 | } | ||
342 | if (!MACH_IS_MEDUSA && !MACH_IS_HADES && | ||
343 | hwreg_present( &tt_dmasnd.ctrl )) { | ||
344 | ATARIHW_SET(PCM_8BIT); | ||
345 | printk( "PCM " ); | ||
346 | } | ||
347 | if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) { | ||
348 | ATARIHW_SET(CODEC); | ||
349 | printk( "CODEC " ); | ||
350 | } | ||
351 | if (hwreg_present( &dsp56k_host_interface.icr )) { | ||
352 | ATARIHW_SET(DSP56K); | ||
353 | printk( "DSP56K " ); | ||
354 | } | ||
355 | if (hwreg_present( &tt_scc_dma.dma_ctrl ) && | ||
356 | #if 0 | ||
357 | /* This test sucks! Who knows some better? */ | ||
358 | (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) && | ||
359 | (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0) | ||
360 | #else | ||
361 | !MACH_IS_MEDUSA && !MACH_IS_HADES | ||
362 | #endif | ||
363 | ) { | ||
364 | ATARIHW_SET(SCC_DMA); | ||
365 | printk( "SCC_DMA " ); | ||
366 | } | ||
367 | if (scc_test( &scc.cha_a_ctrl )) { | ||
368 | ATARIHW_SET(SCC); | ||
369 | printk( "SCC " ); | ||
370 | } | ||
371 | if (scc_test( &st_escc.cha_b_ctrl )) { | ||
372 | ATARIHW_SET( ST_ESCC ); | ||
373 | printk( "ST_ESCC " ); | ||
374 | } | ||
375 | if (MACH_IS_HADES) | ||
376 | { | ||
377 | ATARIHW_SET( VME ); | ||
378 | printk( "VME " ); | ||
379 | } | ||
380 | else if (hwreg_present( &tt_scu.sys_mask )) { | ||
381 | ATARIHW_SET(SCU); | ||
382 | /* Assume a VME bus if there's a SCU */ | ||
383 | ATARIHW_SET( VME ); | ||
384 | printk( "VME SCU " ); | ||
385 | } | ||
386 | if (hwreg_present( (void *)(0xffff9210) )) { | ||
387 | ATARIHW_SET(ANALOG_JOY); | ||
388 | printk( "ANALOG_JOY " ); | ||
389 | } | ||
390 | if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) { | ||
391 | ATARIHW_SET(BLITTER); | ||
392 | printk( "BLITTER " ); | ||
393 | } | ||
394 | if (hwreg_present((void *)0xfff00039)) { | ||
395 | ATARIHW_SET(IDE); | ||
396 | printk( "IDE " ); | ||
397 | } | ||
398 | #if 1 /* This maybe wrong */ | ||
399 | if (!MACH_IS_MEDUSA && !MACH_IS_HADES && | ||
400 | hwreg_present( &tt_microwire.data ) && | ||
401 | hwreg_present( &tt_microwire.mask ) && | ||
402 | (tt_microwire.mask = 0x7ff, | ||
403 | udelay(1), | ||
404 | tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR, | ||
405 | udelay(1), | ||
406 | tt_microwire.data != 0)) { | ||
407 | ATARIHW_SET(MICROWIRE); | ||
408 | while (tt_microwire.mask != 0x7ff) ; | ||
409 | printk( "MICROWIRE " ); | ||
410 | } | ||
411 | #endif | ||
412 | if (hwreg_present( &tt_rtc.regsel )) { | ||
413 | ATARIHW_SET(TT_CLK); | ||
414 | printk( "TT_CLK " ); | ||
415 | mach_hwclk = atari_tt_hwclk; | ||
416 | mach_set_clock_mmss = atari_tt_set_clock_mmss; | ||
417 | } | ||
418 | if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) { | ||
419 | ATARIHW_SET(MSTE_CLK); | ||
420 | printk( "MSTE_CLK "); | ||
421 | mach_hwclk = atari_mste_hwclk; | ||
422 | mach_set_clock_mmss = atari_mste_set_clock_mmss; | ||
423 | } | ||
424 | if (!MACH_IS_MEDUSA && !MACH_IS_HADES && | ||
425 | hwreg_present( &dma_wd.fdc_speed ) && | ||
426 | hwreg_write( &dma_wd.fdc_speed, 0 )) { | ||
427 | ATARIHW_SET(FDCSPEED); | ||
428 | printk( "FDC_SPEED "); | ||
429 | } | ||
430 | if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) { | ||
431 | ATARIHW_SET(ACSI); | ||
432 | printk( "ACSI " ); | ||
433 | } | ||
434 | printk("\n"); | ||
435 | |||
436 | if (CPU_IS_040_OR_060) | ||
437 | /* Now it seems to be safe to turn of the tt0 transparent | ||
438 | * translation (the one that must not be turned off in | ||
439 | * head.S...) | ||
440 | */ | ||
441 | __asm__ volatile ("moveq #0,%/d0\n\t" | ||
442 | ".chip 68040\n\t" | ||
443 | "movec %%d0,%%itt0\n\t" | ||
444 | "movec %%d0,%%dtt0\n\t" | ||
445 | ".chip 68k" | ||
446 | : /* no outputs */ | ||
447 | : /* no inputs */ | ||
448 | : "d0"); | ||
449 | |||
450 | /* allocator for memory that must reside in st-ram */ | ||
451 | atari_stram_init (); | ||
452 | |||
453 | /* Set up a mapping for the VMEbus address region: | ||
454 | * | ||
455 | * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff | ||
456 | * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at | ||
457 | * 0xfe000000 virt., because this can be done with a single | ||
458 | * transparent translation. On the 68040, lots of often unused | ||
459 | * page tables would be needed otherwise. On a MegaSTE or similar, | ||
460 | * the highest byte is stripped off by hardware due to the 24 bit | ||
461 | * design of the bus. | ||
462 | */ | ||
463 | |||
464 | if (CPU_IS_020_OR_030) { | ||
465 | unsigned long tt1_val; | ||
466 | tt1_val = 0xfe008543; /* Translate 0xfexxxxxx, enable, cache | ||
467 | * inhibit, read and write, FDC mask = 3, | ||
468 | * FDC val = 4 -> Supervisor only */ | ||
469 | __asm__ __volatile__ ( ".chip 68030\n\t" | ||
470 | "pmove %0@,%/tt1\n\t" | ||
471 | ".chip 68k" | ||
472 | : : "a" (&tt1_val) ); | ||
473 | } | ||
474 | else { | ||
475 | __asm__ __volatile__ | ||
476 | ( "movel %0,%/d0\n\t" | ||
477 | ".chip 68040\n\t" | ||
478 | "movec %%d0,%%itt1\n\t" | ||
479 | "movec %%d0,%%dtt1\n\t" | ||
480 | ".chip 68k" | ||
481 | : | ||
482 | : "g" (0xfe00a040) /* Translate 0xfexxxxxx, enable, | ||
483 | * supervisor only, non-cacheable/ | ||
484 | * serialized, writable */ | ||
485 | : "d0" ); | ||
486 | |||
487 | } | ||
488 | |||
489 | /* Fetch tos version at Physical 2 */ | ||
490 | /* We my not be able to access this address if the kernel is | ||
491 | loaded to st ram, since the first page is unmapped. On the | ||
492 | Medusa this is always the case and there is nothing we can do | ||
493 | about this, so we just assume the smaller offset. For the TT | ||
494 | we use the fact that in head.S we have set up a mapping | ||
495 | 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible | ||
496 | in the last 16MB of the address space. */ | ||
497 | tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ? | ||
498 | 0xfff : *(unsigned short *)0xff000002; | ||
499 | atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68; | ||
500 | } | ||
501 | |||
502 | #ifdef CONFIG_HEARTBEAT | ||
503 | static void atari_heartbeat( int on ) | ||
504 | { | ||
505 | unsigned char tmp; | ||
506 | unsigned long flags; | ||
507 | |||
508 | if (atari_dont_touch_floppy_select) | ||
509 | return; | ||
510 | |||
511 | local_irq_save(flags); | ||
512 | sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */ | ||
513 | tmp = sound_ym.rd_data_reg_sel; | ||
514 | sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02); | ||
515 | local_irq_restore(flags); | ||
516 | } | ||
517 | #endif | ||
518 | |||
519 | /* ++roman: | ||
520 | * | ||
521 | * This function does a reset on machines that lack the ability to | ||
522 | * assert the processor's _RESET signal somehow via hardware. It is | ||
523 | * based on the fact that you can find the initial SP and PC values | ||
524 | * after a reset at physical addresses 0 and 4. This works pretty well | ||
525 | * for Atari machines, since the lowest 8 bytes of physical memory are | ||
526 | * really ROM (mapped by hardware). For other 680x0 machines: don't | ||
527 | * know if it works... | ||
528 | * | ||
529 | * To get the values at addresses 0 and 4, the MMU better is turned | ||
530 | * off first. After that, we have to jump into physical address space | ||
531 | * (the PC before the pmove statement points to the virtual address of | ||
532 | * the code). Getting that physical address is not hard, but the code | ||
533 | * becomes a bit complex since I've tried to ensure that the jump | ||
534 | * statement after the pmove is in the cache already (otherwise the | ||
535 | * processor can't fetch it!). For that, the code first jumps to the | ||
536 | * jump statement with the (virtual) address of the pmove section in | ||
537 | * an address register . The jump statement is surely in the cache | ||
538 | * now. After that, that physical address of the reset code is loaded | ||
539 | * into the same address register, pmove is done and the same jump | ||
540 | * statements goes to the reset code. Since there are not many | ||
541 | * statements between the two jumps, I hope it stays in the cache. | ||
542 | * | ||
543 | * The C code makes heavy use of the GCC features that you can get the | ||
544 | * address of a C label. No hope to compile this with another compiler | ||
545 | * than GCC! | ||
546 | */ | ||
547 | |||
548 | /* ++andreas: no need for complicated code, just depend on prefetch */ | ||
549 | |||
550 | static void atari_reset (void) | ||
551 | { | ||
552 | long tc_val = 0; | ||
553 | long reset_addr; | ||
554 | |||
555 | /* On the Medusa, phys. 0x4 may contain garbage because it's no | ||
556 | ROM. See above for explanation why we cannot use PTOV(4). */ | ||
557 | reset_addr = MACH_IS_HADES ? 0x7fe00030 : | ||
558 | MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 : | ||
559 | *(unsigned long *) 0xff000004; | ||
560 | |||
561 | /* reset ACIA for switch off OverScan, if it's active */ | ||
562 | if (atari_switches & ATARI_SWITCH_OVSC_IKBD) | ||
563 | acia.key_ctrl = ACIA_RESET; | ||
564 | if (atari_switches & ATARI_SWITCH_OVSC_MIDI) | ||
565 | acia.mid_ctrl = ACIA_RESET; | ||
566 | |||
567 | /* processor independent: turn off interrupts and reset the VBR; | ||
568 | * the caches must be left enabled, else prefetching the final jump | ||
569 | * instruction doesn't work. */ | ||
570 | local_irq_disable(); | ||
571 | __asm__ __volatile__ | ||
572 | ("moveq #0,%/d0\n\t" | ||
573 | "movec %/d0,%/vbr" | ||
574 | : : : "d0" ); | ||
575 | |||
576 | if (CPU_IS_040_OR_060) { | ||
577 | unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040); | ||
578 | if (CPU_IS_060) { | ||
579 | /* 68060: clear PCR to turn off superscalar operation */ | ||
580 | __asm__ __volatile__ | ||
581 | ("moveq #0,%/d0\n\t" | ||
582 | ".chip 68060\n\t" | ||
583 | "movec %%d0,%%pcr\n\t" | ||
584 | ".chip 68k" | ||
585 | : : : "d0" ); | ||
586 | } | ||
587 | |||
588 | __asm__ __volatile__ | ||
589 | ("movel %0,%/d0\n\t" | ||
590 | "andl #0xff000000,%/d0\n\t" | ||
591 | "orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */ | ||
592 | ".chip 68040\n\t" | ||
593 | "movec %%d0,%%itt0\n\t" | ||
594 | "movec %%d0,%%dtt0\n\t" | ||
595 | ".chip 68k\n\t" | ||
596 | "jmp %0@\n\t" | ||
597 | : /* no outputs */ | ||
598 | : "a" (jmp_addr040) | ||
599 | : "d0" ); | ||
600 | jmp_addr_label040: | ||
601 | __asm__ __volatile__ | ||
602 | ("moveq #0,%/d0\n\t" | ||
603 | "nop\n\t" | ||
604 | ".chip 68040\n\t" | ||
605 | "cinva %%bc\n\t" | ||
606 | "nop\n\t" | ||
607 | "pflusha\n\t" | ||
608 | "nop\n\t" | ||
609 | "movec %%d0,%%tc\n\t" | ||
610 | "nop\n\t" | ||
611 | /* the following setup of transparent translations is needed on the | ||
612 | * Afterburner040 to successfully reboot. Other machines shouldn't | ||
613 | * care about a different tt regs setup, they also didn't care in | ||
614 | * the past that the regs weren't turned off. */ | ||
615 | "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */ | ||
616 | "movec %%d0,%%itt0\n\t" | ||
617 | "movec %%d0,%%itt1\n\t" | ||
618 | "orw #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */ | ||
619 | "movec %%d0,%%dtt0\n\t" | ||
620 | "movec %%d0,%%dtt1\n\t" | ||
621 | ".chip 68k\n\t" | ||
622 | "jmp %0@" | ||
623 | : /* no outputs */ | ||
624 | : "a" (reset_addr) | ||
625 | : "d0"); | ||
626 | } | ||
627 | else | ||
628 | __asm__ __volatile__ | ||
629 | ("pmove %0@,%/tc\n\t" | ||
630 | "jmp %1@" | ||
631 | : /* no outputs */ | ||
632 | : "a" (&tc_val), "a" (reset_addr)); | ||
633 | } | ||
634 | |||
635 | |||
636 | static void atari_get_model(char *model) | ||
637 | { | ||
638 | strcpy(model, "Atari "); | ||
639 | switch (atari_mch_cookie >> 16) { | ||
640 | case ATARI_MCH_ST: | ||
641 | if (ATARIHW_PRESENT(MSTE_CLK)) | ||
642 | strcat (model, "Mega ST"); | ||
643 | else | ||
644 | strcat (model, "ST"); | ||
645 | break; | ||
646 | case ATARI_MCH_STE: | ||
647 | if (MACH_IS_MSTE) | ||
648 | strcat (model, "Mega STE"); | ||
649 | else | ||
650 | strcat (model, "STE"); | ||
651 | break; | ||
652 | case ATARI_MCH_TT: | ||
653 | if (MACH_IS_MEDUSA) | ||
654 | /* Medusa has TT _MCH cookie */ | ||
655 | strcat (model, "Medusa"); | ||
656 | else if (MACH_IS_HADES) | ||
657 | strcat(model, "Hades"); | ||
658 | else | ||
659 | strcat (model, "TT"); | ||
660 | break; | ||
661 | case ATARI_MCH_FALCON: | ||
662 | strcat (model, "Falcon"); | ||
663 | if (MACH_IS_AB40) | ||
664 | strcat (model, " (with Afterburner040)"); | ||
665 | break; | ||
666 | default: | ||
667 | sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)", | ||
668 | atari_mch_cookie); | ||
669 | break; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | |||
674 | static int atari_get_hardware_list(char *buffer) | ||
675 | { | ||
676 | int len = 0, i; | ||
677 | |||
678 | for (i = 0; i < m68k_num_memory; i++) | ||
679 | len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n", | ||
680 | m68k_memory[i].size >> 20, m68k_memory[i].addr, | ||
681 | (m68k_memory[i].addr & 0xff000000 ? | ||
682 | "alternate RAM" : "ST-RAM")); | ||
683 | |||
684 | #define ATARIHW_ANNOUNCE(name,str) \ | ||
685 | if (ATARIHW_PRESENT(name)) \ | ||
686 | len += sprintf (buffer + len, "\t%s\n", str) | ||
687 | |||
688 | len += sprintf (buffer + len, "Detected hardware:\n"); | ||
689 | ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter"); | ||
690 | ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter"); | ||
691 | ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter"); | ||
692 | ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter"); | ||
693 | ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator"); | ||
694 | ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound"); | ||
695 | ATARIHW_ANNOUNCE(CODEC, "CODEC Sound"); | ||
696 | ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)"); | ||
697 | ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)"); | ||
698 | ATARIHW_ANNOUNCE(ACSI, "ACSI Interface"); | ||
699 | ATARIHW_ANNOUNCE(IDE, "IDE Interface"); | ||
700 | ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC"); | ||
701 | ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901"); | ||
702 | ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901"); | ||
703 | ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530"); | ||
704 | ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230"); | ||
705 | ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface"); | ||
706 | ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface"); | ||
707 | ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)"); | ||
708 | ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)"); | ||
709 | ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380"); | ||
710 | ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC"); | ||
711 | ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A"); | ||
712 | ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15"); | ||
713 | ATARIHW_ANNOUNCE(SCU, "System Control Unit"); | ||
714 | ATARIHW_ANNOUNCE(BLITTER, "Blitter"); | ||
715 | ATARIHW_ANNOUNCE(VME, "VME Bus"); | ||
716 | ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor"); | ||
717 | |||
718 | return(len); | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * Local variables: | ||
723 | * c-indent-level: 4 | ||
724 | * tab-width: 8 | ||
725 | * End: | ||
726 | */ | ||