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