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