root/arch/m68k/atari/config.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwreg_present
  2. hwreg_present_bywrite
  3. hwreg_write
  4. scc_test
  5. config_atari
  6. atari_sched_init
  7. atari_gettimeoffset
  8. mste_read
  9. mste_write
  10. atari_mste_gettod
  11. atari_gettod
  12. atari_mste_hwclk
  13. atari_hwclk
  14. atari_mste_set_clock_mmss
  15. atari_set_clock_mmss
  16. atari_waitbut
  17. ata_mfp_out
  18. ata_mfp_print
  19. ata_scc_out
  20. ata_scc_print
  21. ata_par_out
  22. ata_par_print
  23. atari_debug_init
  24. ata_serial_print
  25. atari_reset
  26. atari_get_model
  27. atari_get_hardware_list

   1 /*
   2  *  linux/atari/config.c
   3  *
   4  *  Copyright (C) 1994 Bj”rn 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 README.legal 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 <asm/bootinfo.h>
  31 #include <linux/mc146818rtc.h>
  32 #include <linux/kd.h>
  33 #include <linux/tty.h>
  34 #include <linux/console.h>
  35 
  36 #include <asm/atarihw.h>
  37 #include <asm/atarihdreg.h>
  38 #include <asm/atariints.h>
  39 
  40 #include <asm/system.h>
  41 #include <asm/io.h>
  42 #include <asm/irq.h>
  43 #include <asm/pgtable.h>
  44 #include <asm/machdep.h>
  45 
  46 extern void atari_sched_init(isrfunc);
  47 extern int atari_keyb_init(void);
  48 extern int atari_kbdrate (struct kbd_repeat *);
  49 extern void atari_kbd_leds (unsigned int);
  50 extern void atari_init_INTS (void);
  51 extern int atari_add_isr (unsigned long, isrfunc, int, void *, char *);
  52 extern int atari_remove_isr (unsigned long, isrfunc);
  53 extern void atari_enable_irq (unsigned);
  54 extern void atari_disable_irq (unsigned);
  55 extern int atari_get_irq_list (char *buf, int len);
  56 extern unsigned long atari_gettimeoffset (void);
  57 extern void atari_mste_gettod (int *, int *, int *, int *, int *, int *);
  58 extern void atari_gettod (int *, int *, int *, int *, int *, int *);
  59 extern int atari_mste_hwclk (int, struct hwclk_time *);
  60 extern int atari_hwclk (int, struct hwclk_time *);
  61 extern int atari_mste_set_clock_mmss (unsigned long);
  62 extern int atari_set_clock_mmss (unsigned long);
  63 extern void atari_mksound( unsigned int count, unsigned int ticks );
  64 extern void atari_reset( void );
  65 #ifdef CONFIG_BLK_DEV_FD
  66 extern int atari_floppy_init (void);
  67 extern void atari_floppy_setup(char *, int *);
  68 #endif
  69 extern void atari_waitbut (void);
  70 extern struct consw fb_con;
  71 extern struct fb_info *atari_fb_init(long *);
  72 extern void atari_debug_init (void);
  73 extern void atari_video_setup(char *, int *);
  74 
  75 extern void (*kd_mksound)(unsigned int, unsigned int);
  76 
  77 /* This function tests for the presence of an address, specially a
  78  * hardware register address. It is called very early in the kernel
  79  * initialization process, when the VBR register isn't set up yet. On
  80  * an Atari, it still points to address 0, which is unmapped. So a bus
  81  * error would cause another bus error while fetching the exception
  82  * vector, and the CPU would do nothing at all. So we needed to set up
  83  * a temporary VBR and a vector table for the duration of the test.
  84  */
  85 
  86 static int hwreg_present( volatile void *regp )
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88     int ret = 0;
  89     long        save_sp, save_vbr;
  90     long        tmp_vectors[3];
  91 
  92     __asm__ __volatile__
  93         (       "movec  %/vbr,%2\n\t"
  94                 "movel  #Lberr1,%4@(8)\n\t"
  95                 "movec  %4,%/vbr\n\t"
  96                 "movel  %/sp,%1\n\t"
  97                 "moveq  #0,%0\n\t"
  98                 "tstb   %3@\n\t"  
  99                 "nop\n\t"
 100                 "moveq  #1,%0\n"
 101                 "Lberr1:\n\t"
 102                 "movel  %1,%/sp\n\t"
 103                 "movec  %2,%/vbr"
 104                 : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
 105                 : "a" (regp), "a" (tmp_vectors)
 106                 );
 107 
 108     return( ret );
 109 }
 110   
 111 #if 0
 112 static int hwreg_present_bywrite( volatile void *regp,
     /* [previous][next][first][last][top][bottom][index][help] */
 113                                  unsigned char val )
 114 
 115 {
 116     int         ret;
 117     long        save_sp, save_vbr;
 118     static long tmp_vectors[3] = { 0, 0, (long)&&after_test };
 119         
 120     __asm__ __volatile__
 121         (       "movec  %/vbr,%2\n\t"   /* save vbr value            */
 122                 "movec  %4,%/vbr\n\t"   /* set up temporary vectors  */
 123                 "movel  %/sp,%1\n\t"    /* save sp                   */
 124                 "moveq  #0,%0\n\t"      /* assume not present        */
 125                 "moveb  %5,%3@\n\t"     /* write the hardware reg    */
 126                 "cmpb   %3@,%5\n\t"     /* compare it                */
 127                 "seq    %0"             /* comes here only if reg    */
 128                                         /* is present                */
 129                 : "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
 130                 : "a" (regp), "r" (tmp_vectors), "d" (val)
 131                 );
 132   after_test:
 133     __asm__ __volatile__
 134       ( "movel  %0,%/sp\n\t"            /* restore sp                */
 135         "movec  %1,%/vbr"                       /* restore vbr               */
 136         : : "r" (save_sp), "r" (save_vbr) : "sp"
 137         );
 138 
 139     return( ret );
 140 }
 141 #endif
 142 
 143 /* Basically the same, but writes a value into a word register, protected
 144  * by a bus error handler */
 145 
 146 static int hwreg_write( volatile void *regp, unsigned short val )
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         int             ret;
 149         long    save_sp, save_vbr;
 150         long    tmp_vectors[3];
 151 
 152         __asm__ __volatile__
 153         (       "movec  %/vbr,%2\n\t"
 154                 "movel  #Lberr2,%4@(8)\n\t"
 155                 "movec  %4,%/vbr\n\t"
 156                 "movel  %/sp,%1\n\t"
 157                 "moveq  #0,%0\n\t"
 158                 "movew  %5,%3@\n\t"  
 159                 "nop    \n\t"   /* If this nop isn't present, 'ret' may already be
 160                                  * loaded with 1 at the time the bus error
 161                                  * happens! */
 162                 "moveq  #1,%0\n"
 163         "Lberr2:\n\t"
 164                 "movel  %1,%/sp\n\t"
 165                 "movec  %2,%/vbr"
 166                 : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
 167                 : "a" (regp), "a" (tmp_vectors), "g" (val)
 168         );
 169 
 170         return( ret );
 171 }
 172 
 173 /* ++roman: This is a more elaborate test for an SCC chip, since the plain
 174  * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
 175  * board in the Medusa is possible. Also, the addresses where the ST_ESCC
 176  * resides generate DTACK without the chip, too.
 177  * The method is to write values into the interrupt vector register, that
 178  * should be readable without trouble (from channel A!).
 179  */
 180 
 181 static int scc_test( volatile char *ctla )
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         if (!hwreg_present( ctla ))
 184                 return( 0 );
 185         MFPDELAY();
 186 
 187         *ctla = 2; MFPDELAY();
 188         *ctla = 0x40; MFPDELAY();
 189         
 190         *ctla = 2; MFPDELAY();
 191         if (*ctla != 0x40) return( 0 );
 192         MFPDELAY();
 193 
 194         *ctla = 2; MFPDELAY();
 195         *ctla = 0x60; MFPDELAY();
 196         
 197         *ctla = 2; MFPDELAY();
 198         if (*ctla != 0x60) return( 0 );
 199 
 200         return( 1 );
 201 }
 202 
 203 void config_atari(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205     mach_sched_init      = atari_sched_init;
 206     mach_keyb_init       = atari_keyb_init;
 207     mach_kbdrate         = atari_kbdrate;
 208     mach_kbd_leds        = atari_kbd_leds;
 209     mach_init_INTS       = atari_init_INTS;
 210     mach_add_isr         = atari_add_isr;
 211     mach_remove_isr      = atari_remove_isr;
 212     mach_enable_irq      = atari_enable_irq;
 213     mach_disable_irq     = atari_disable_irq;
 214     mach_get_irq_list    = atari_get_irq_list;
 215     mach_gettimeoffset   = atari_gettimeoffset;
 216     mach_mksound         = atari_mksound;
 217     mach_reset           = atari_reset;
 218 #ifdef CONFIG_BLK_DEV_FD
 219     mach_floppy_init     = atari_floppy_init;
 220     mach_floppy_setup    = atari_floppy_setup;
 221 #endif
 222     conswitchp           = &fb_con;
 223     waitbut              = atari_waitbut;
 224     mach_fb_init         = atari_fb_init;
 225     mach_max_dma_address = 0xffffff;
 226     mach_debug_init      = atari_debug_init;
 227     mach_video_setup     = atari_video_setup;
 228     kd_mksound           = atari_mksound;
 229 
 230     /* ++bjoern: 
 231      * Determine hardware present
 232      */
 233 
 234     printk( "Atari hardware found: " );
 235     if (is_medusa) {
 236         /* There's no Atari video hardware on the Medusa, but all the
 237          * addresses below generate a DTACK so no bus error occurs! */
 238     }
 239     else if (hwreg_present( f030_xreg )) {
 240         ATARIHW_SET(VIDEL_SHIFTER);
 241         printk( "VIDEL " );
 242         /* This is a temporary hack: If there is Falcon video
 243          * hardware, we assume that the ST-DMA serves SCSI instead of
 244          * ACSI. In the future, there should be a better method for
 245          * this...
 246          */
 247         ATARIHW_SET(ST_SCSI);
 248         printk( "STDMA-SCSI " );
 249     }
 250     else if (hwreg_present( tt_palette )) {
 251         ATARIHW_SET(TT_SHIFTER);
 252         printk( "TT_SHIFTER " );
 253     }
 254     else if (hwreg_present( &shifter.bas_hi )) {
 255         if (hwreg_present( &shifter.bas_lo ) &&
 256             (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
 257             ATARIHW_SET(EXTD_SHIFTER);
 258             printk( "EXTD_SHIFTER " );
 259         }
 260         else {
 261             ATARIHW_SET(STND_SHIFTER);
 262             printk( "STND_SHIFTER " );
 263         }
 264     }
 265     if (hwreg_present( &mfp.par_dt_reg )) {
 266         ATARIHW_SET(ST_MFP);
 267         printk( "ST_MFP " );
 268     }
 269     if (hwreg_present( &tt_mfp.par_dt_reg )) {
 270         ATARIHW_SET(TT_MFP);
 271         printk( "TT_MFP " );
 272     }
 273     if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
 274         ATARIHW_SET(SCSI_DMA);
 275         printk( "TT_SCSI_DMA " );
 276     }
 277     if (hwreg_present( &st_dma.dma_hi )) {
 278         ATARIHW_SET(STND_DMA);
 279         printk( "STND_DMA " );
 280     }
 281     if (is_medusa || /* The ST-DMA address registers aren't readable
 282                       * on all Medusas, so the test below may fail */
 283         (hwreg_present( &st_dma.dma_vhi ) &&
 284          (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
 285          st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
 286          (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
 287          st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
 288         ATARIHW_SET(EXTD_DMA);
 289         printk( "EXTD_DMA " );
 290     }
 291     if (hwreg_present( &tt_scsi.scsi_data )) {
 292         ATARIHW_SET(TT_SCSI);
 293         printk( "TT_SCSI " );
 294     }
 295     if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
 296         ATARIHW_SET(YM_2149);
 297         printk( "YM2149 " );
 298     }
 299     if (!is_medusa && hwreg_present( &tt_dmasnd.ctrl )) {
 300         ATARIHW_SET(PCM_8BIT);
 301         printk( "PCM " );
 302     }
 303     if (hwreg_present( (void *)(0xffff8940) )) {
 304         ATARIHW_SET(CODEC);
 305         printk( "CODEC " );
 306     }
 307     if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
 308 #if 0
 309         /* This test sucks! Who knows some better? */
 310         (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
 311         (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
 312 #else
 313         !is_medusa
 314 #endif
 315         ) {
 316         ATARIHW_SET(SCC_DMA);
 317         printk( "SCC_DMA " );
 318     }
 319     if (scc_test( &scc.cha_a_ctrl )) {
 320         ATARIHW_SET(SCC);
 321         printk( "SCC " );
 322     }
 323     if (scc_test( &st_escc.cha_b_ctrl )) {
 324         ATARIHW_SET( ST_ESCC );
 325         printk( "ST_ESCC " );
 326     }
 327     if (hwreg_present( &tt_scu.sys_mask )) {
 328         ATARIHW_SET(SCU);
 329         /* Assume a VME bus if there's a SCU */
 330         ATARIHW_SET( VME );
 331         printk( "VME SCU " );
 332     }
 333     if (hwreg_present( (void *)(0xffff9210) )) {
 334         ATARIHW_SET(ANALOG_JOY);
 335         printk( "ANALOG_JOY " );
 336     }
 337     if (hwreg_present( blitter.halftone )) {
 338         ATARIHW_SET(BLITTER);
 339         printk( "BLITTER " );
 340     }
 341     if (hwreg_present( (void *)(ATA_HD_BASE+ATA_HD_CMD) )) {
 342         ATARIHW_SET(IDE);
 343         printk( "IDE " );
 344     }
 345 #if 1 /* This maybe wrong */
 346     if (!is_medusa &&
 347         hwreg_present( &tt_microwire.data ) &&
 348         hwreg_present( &tt_microwire.mask ) &&
 349         (tt_microwire.mask = 0x7ff,
 350          tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
 351          tt_microwire.data != 0)) {
 352         ATARIHW_SET(MICROWIRE);
 353         while (tt_microwire.mask != 0x7ff) ;
 354         printk( "MICROWIRE " );
 355     }
 356 #endif
 357     if (hwreg_present( &tt_rtc.regsel )) {
 358         ATARIHW_SET(TT_CLK);
 359         printk( "TT_CLK " );
 360         mach_gettod = atari_gettod;
 361         mach_hwclk = atari_hwclk;
 362         mach_set_clock_mmss = atari_set_clock_mmss;
 363     }
 364     if (hwreg_present( &mste_rtc.sec_ones)) {
 365         ATARIHW_SET(MSTE_CLK);
 366         printk( "MSTE_CLK ");
 367         mach_gettod = atari_mste_gettod;
 368         mach_hwclk = atari_mste_hwclk;
 369         mach_set_clock_mmss = atari_mste_set_clock_mmss;
 370     }
 371     if (!is_medusa &&
 372         hwreg_present( &dma_wd.fdc_speed ) &&
 373         hwreg_write( &dma_wd.fdc_speed, 0 )) {
 374             ATARIHW_SET(FDCSPEED);
 375             printk( "FDC_SPEED ");
 376     }
 377     if (!ATARIHW_PRESENT(ST_SCSI)) {
 378         ATARIHW_SET(ACSI);
 379         printk( "ACSI " );
 380     }
 381     printk("\n");
 382 
 383     if (m68k_is040or060)
 384         /* Now it seems to be safe to turn of the tt0 transparent
 385          * translation (the one that must not be turned off in
 386          * head.S...)
 387          */
 388         __asm__ volatile ("moveq #0,%/d0;"
 389                           ".long 0x4e7b0004;"   /* movec d0,itt0 */
 390                           ".long 0x4e7b0006;"   /* movec d0,dtt0 */
 391                                                   : /* no outputs */
 392                                                   : /* no inputs */
 393                                                   : "d0");
 394         
 395     /* allocator for memory that must reside in st-ram */
 396     atari_stram_init ();
 397 
 398     /* Set up a mapping for the VMEbus address region:
 399      *
 400      * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
 401      * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
 402      * 0xfe000000 virt., because this can be done with a single
 403      * transparent translation. On the 68040, lots of often unused
 404      * page tables would be needed otherwise. On a MegaSTE or similar,
 405      * the highest byte is stripped off by hardware due to the 24 bit
 406      * design of the bus.
 407      */
 408 
 409     if (!m68k_is040or060) {
 410         unsigned long   tt1_val;
 411         tt1_val = 0xfe008543;   /* Translate 0xfexxxxxx, enable, cache
 412                                  * inhibit, read and write, FDC mask = 3,
 413                                  * FDC val = 4 -> Supervisor only */
 414         __asm__ __volatile__ ( "pmove   %0@,%/tt1" : : "a" (&tt1_val) );
 415     }
 416     else {
 417         __asm__ __volatile__
 418             ( "movel %0,%/d0\n\t"
 419               ".long 0x4e7b0005\n\t"    /* movec d0,itt1 */
 420               ".long 0x4e7b0007"        /* movec d0,dtt1 */
 421               :
 422               : "g" (0xfe00a040)        /* Translate 0xfexxxxxx, enable,
 423                                          * supervisor only, non-cacheable/
 424                                          * serialized, writable */
 425               : "d0" );
 426 
 427     }
 428 }
 429 
 430 void atari_sched_init (isrfunc timer_routine)
     /* [previous][next][first][last][top][bottom][index][help] */
 431 {
 432     /* set Timer C data Register */
 433     mfp.tim_dt_c = INT_TICKS;
 434     /* start timer C, div = 1:100 */
 435     mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60; 
 436     /* install interrupt service routine for MFP Timer C */
 437     add_isr (IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW, NULL, "timer");
 438 }
 439 
 440 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
 441 
 442 #define TICK_SIZE 10000
 443   
 444 /* This is always executed with interrupts disabled.  */
 445 unsigned long atari_gettimeoffset (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447   unsigned long ticks, offset = 0;
 448 
 449   /* read MFP timer C current value */
 450   ticks = mfp.tim_dt_c;
 451   /* The probability of underflow is less than 2% */
 452   if (ticks > INT_TICKS - INT_TICKS / 50)
 453     /* Check for pending timer interrupt */
 454     if (mfp.int_pn_b & (1 << 5))
 455       offset = TICK_SIZE;
 456 
 457   ticks = INT_TICKS - ticks;
 458   ticks = ticks * 10000L / INT_TICKS;
 459 
 460   return ticks + offset;
 461 }
 462 
 463 
 464 static void
 465 mste_read(struct MSTE_RTC *val)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467 #define COPY(v) val->v=(mste_rtc.v & 0xf)
 468         do {
 469                 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ; 
 470                 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ; 
 471                 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ; 
 472                 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
 473                 COPY(year_tens) ;
 474         /* prevent from reading the clock while it changed */
 475         } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
 476 #undef COPY
 477 }
 478 
 479 static void
 480 mste_write(struct MSTE_RTC *val)
     /* [previous][next][first][last][top][bottom][index][help] */
 481 {
 482 #define COPY(v) mste_rtc.v=val->v
 483         do {
 484                 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ; 
 485                 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ; 
 486                 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ; 
 487                 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
 488                 COPY(year_tens) ;
 489         /* prevent from writing the clock while it changed */
 490         } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
 491 #undef COPY
 492 }
 493 
 494 #define RTC_READ(reg)                           \
 495     ({  unsigned char   __val;                  \
 496                 outb(reg,&tt_rtc.regsel);       \
 497                 __val = tt_rtc.data;            \
 498                 __val;                          \
 499         })
 500 
 501 #define RTC_WRITE(reg,val)                      \
 502     do {                                        \
 503                 outb(reg,&tt_rtc.regsel);       \
 504                 tt_rtc.data = (val);            \
 505         } while(0)
 506 
 507 
 508 void atari_mste_gettod (int *yearp, int *monp, int *dayp,
     /* [previous][next][first][last][top][bottom][index][help] */
 509                         int *hourp, int *minp, int *secp)
 510 {
 511     int hr24=0;
 512     struct MSTE_RTC val;
 513 
 514     mste_rtc.mode=(mste_rtc.mode | 1);
 515     hr24=mste_rtc.mon_tens & 1;
 516     mste_rtc.mode=(mste_rtc.mode & ~1);
 517 
 518     mste_read(&val);
 519     *secp = val.sec_ones + val.sec_tens * 10;
 520     *minp = val.min_ones + val.min_tens * 10;
 521     if (hr24)
 522         *hourp = val.hr_ones + val.hr_tens * 10;
 523     else {
 524         *hourp = val.hr_ones + (val.hr_tens & 1) * 10;
 525         if (val.hr_tens & 2)
 526             *hourp += 12;
 527     }
 528     *dayp = val.day_ones + val.day_tens * 10;
 529     *monp = val.mon_ones + val.mon_tens * 10;
 530     *yearp = val.year_ones + val.year_tens * 10 + 80;   
 531 }
 532 
 533   
 534 void atari_gettod (int *yearp, int *monp, int *dayp,
     /* [previous][next][first][last][top][bottom][index][help] */
 535                    int *hourp, int *minp, int *secp)
 536 {
 537     unsigned char       ctrl;
 538     unsigned short tos_version;
 539                 
 540     while (!(RTC_READ(RTC_FREQ_SELECT) & RTC_UIP)) ;
 541     while (RTC_READ(RTC_FREQ_SELECT) & RTC_UIP) ;
 542 
 543     *secp  = RTC_READ(RTC_SECONDS);
 544     *minp  = RTC_READ(RTC_MINUTES);
 545     *hourp = RTC_READ(RTC_HOURS);
 546     *dayp  = RTC_READ(RTC_DAY_OF_MONTH);
 547     *monp  = RTC_READ(RTC_MONTH);
 548     *yearp = RTC_READ(RTC_YEAR);
 549 
 550     ctrl = RTC_READ(RTC_CONTROL); 
 551 
 552     if (!(ctrl & RTC_DM_BINARY)) {
 553         BCD_TO_BIN(*secp);
 554         BCD_TO_BIN(*minp);
 555         BCD_TO_BIN(*hourp);
 556         BCD_TO_BIN(*dayp);
 557         BCD_TO_BIN(*monp);
 558         BCD_TO_BIN(*yearp);
 559     }
 560     if (!(ctrl & RTC_24H)) {
 561         if (*hourp & 0x80) {
 562             *hourp &= ~0x80;
 563             *hourp += 12;
 564         }
 565     }
 566     /* Adjust values (let the setup valid) */
 567 
 568     /* Fetch tos version at Physical 2 */
 569     /* We my not be able to access this address if the kernel is
 570        loaded to st ram, since the first page is unmapped.  On the
 571        Medusa this is always the case and there is nothing we can do
 572        about this, so we just assume the smaller offset.  For the TT
 573        we use the fact that in head.S we have set up a mapping
 574        0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
 575        in the last 16MB of the address space. */
 576     tos_version = is_medusa ? 0xfff : *(unsigned short *)0xFF000002;
 577     *yearp += (tos_version < 0x306) ? 70 : 68;
 578 }
 579 
 580 #define HWCLK_POLL_INTERVAL     5
 581 
 582 int atari_mste_hwclk( int op, struct hwclk_time *t )
     /* [previous][next][first][last][top][bottom][index][help] */
 583 {
 584     int hour, year;
 585     int hr24=0;
 586     struct MSTE_RTC val;
 587     
 588     mste_rtc.mode=(mste_rtc.mode | 1);
 589     hr24=mste_rtc.mon_tens & 1;
 590     mste_rtc.mode=(mste_rtc.mode & ~1);
 591 
 592     if (op) {
 593         /* write: prepare values */
 594         
 595         val.sec_ones = t->sec % 10;
 596         val.sec_tens = t->sec / 10;
 597         val.min_ones = t->min % 10;
 598         val.min_tens = t->min / 10;
 599         hour = t->hour;
 600         val.hr_ones = hour % 10;
 601         val.hr_tens = hour / 10;
 602         if (!hr24  && hour > 11) {
 603             hour -= 12;
 604             val.hr_ones = hour % 10;
 605             val.hr_tens = (hour / 10) | 2;
 606         }
 607         val.day_ones = t->day % 10;
 608         val.day_tens = t->day / 10;
 609         val.mon_ones = (t->mon+1) % 10;
 610         val.mon_tens = (t->mon+1) / 10;
 611         year = t->year - 80;
 612         val.year_ones = year % 10;
 613         val.year_tens = year / 10;
 614         val.weekday = t->wday;
 615         mste_write(&val);
 616         mste_rtc.mode=(mste_rtc.mode | 1);
 617         val.year_ones = (year % 4);     /* leap year register */
 618         mste_rtc.mode=(mste_rtc.mode & ~1);
 619     }
 620     else {
 621         mste_read(&val);
 622         t->sec = val.sec_ones + val.sec_tens * 10;
 623         t->min = val.min_ones + val.min_tens * 10;
 624         if (hr24)
 625             t->hour = val.hr_ones + val.hr_tens * 10;
 626         else {
 627             t->hour = val.hr_ones + (val.hr_tens & 1) * 10;
 628             if (val.hr_tens & 2)
 629                 t->hour += 12;
 630         }
 631         t->day = val.day_ones + val.day_tens * 10;
 632         t->mon = val.mon_ones + val.mon_tens * 10 - 1;
 633         t->year = val.year_ones + val.year_tens * 10 + 80;
 634         t->wday = val.weekday;
 635     }
 636     return 0;
 637 }
 638 
 639 int atari_hwclk( int op, struct hwclk_time *t )
     /* [previous][next][first][last][top][bottom][index][help] */
 640 {
 641     int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0; 
 642     unsigned long       flags;
 643     unsigned short      tos_version;
 644     unsigned char       ctrl;
 645 
 646     /* Tos version at Physical 2.  See above for explanation why we
 647        cannot use PTOV(2).  */
 648     tos_version = is_medusa ? 0xfff : *(unsigned short *)0xff000002;
 649 
 650     ctrl = RTC_READ(RTC_CONTROL); /* control registers are
 651                                    * independent from the UIP */
 652 
 653     if (op) {
 654         /* write: prepare values */
 655         
 656         sec  = t->sec;
 657         min  = t->min;
 658         hour = t->hour;
 659         day  = t->day;
 660         mon  = t->mon + 1;
 661         year = t->year - ((tos_version < 0x306) ? 70 : 68);
 662         wday = t->wday + (t->wday >= 0);
 663         
 664         if (!(ctrl & RTC_24H) && hour > 11) {
 665             hour -= 12;
 666             hour |= 0x80;
 667         }
 668         
 669         if (!(ctrl & RTC_DM_BINARY)) {
 670             BIN_TO_BCD(sec);
 671             BIN_TO_BCD(min);
 672             BIN_TO_BCD(hour);
 673             BIN_TO_BCD(day);
 674             BIN_TO_BCD(mon);
 675             BIN_TO_BCD(year);
 676             if (wday >= 0) BIN_TO_BCD(wday);
 677         }
 678     }
 679     
 680     /* Reading/writing the clock registers is a bit critical due to
 681      * the regular update cycle of the RTC. While an update is in
 682      * progress, registers 0..9 shouldn't be touched.
 683      * The problem is solved like that: If an update is currently in
 684      * progress (the UIP bit is set), the process sleeps for a while
 685      * (50ms). This really should be enough, since the update cycle
 686      * normally needs 2 ms.
 687      * If the UIP bit reads as 0, we have at least 244 usecs until the
 688      * update starts. This should be enough... But to be sure,
 689      * additionally the RTC_SET bit is set to prevent an update cycle.
 690      */
 691 
 692     while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
 693         current->state = TASK_INTERRUPTIBLE;
 694         current->timeout = jiffies + HWCLK_POLL_INTERVAL;
 695         schedule();
 696     }
 697 
 698     save_flags(flags);
 699     cli();
 700     RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
 701     if (!op) {
 702         sec  = RTC_READ( RTC_SECONDS );
 703         min  = RTC_READ( RTC_MINUTES );
 704         hour = RTC_READ( RTC_HOURS );
 705         day  = RTC_READ( RTC_DAY_OF_MONTH );
 706         mon  = RTC_READ( RTC_MONTH );
 707         year = RTC_READ( RTC_YEAR );
 708         wday = RTC_READ( RTC_DAY_OF_WEEK );
 709     }
 710     else {
 711         RTC_WRITE( RTC_SECONDS, sec );
 712         RTC_WRITE( RTC_MINUTES, min );
 713         RTC_WRITE( RTC_HOURS, hour );
 714         RTC_WRITE( RTC_DAY_OF_MONTH, day );
 715         RTC_WRITE( RTC_MONTH, mon );
 716         RTC_WRITE( RTC_YEAR, year );
 717         if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
 718     }
 719     RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
 720     restore_flags(flags);
 721 
 722     if (!op) {
 723         /* read: adjust values */
 724         
 725         if (!(ctrl & RTC_DM_BINARY)) {
 726             BCD_TO_BIN(sec);
 727             BCD_TO_BIN(min);
 728             BCD_TO_BIN(hour);
 729             BCD_TO_BIN(day);
 730             BCD_TO_BIN(mon);
 731             BCD_TO_BIN(year);
 732             BCD_TO_BIN(wday);
 733         }
 734 
 735         if (!(ctrl & RTC_24H)) {
 736             if (hour & 0x80) {
 737                 hour &= ~0x80;
 738                 hour += 12;
 739             }
 740         }
 741 
 742         t->sec  = sec;
 743         t->min  = min;
 744         t->hour = hour;
 745         t->day  = day;
 746         t->mon  = mon - 1;
 747         t->year = year + ((tos_version < 0x306) ? 70 : 68);
 748         t->wday = wday - 1;
 749     }
 750 
 751     return( 0 );
 752 }
 753 
 754 
 755 int atari_mste_set_clock_mmss (unsigned long nowtime)
     /* [previous][next][first][last][top][bottom][index][help] */
 756 {
 757     short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 758     struct MSTE_RTC val;
 759     unsigned char rtc_minutes;
 760 
 761     mste_read(&val);  
 762     rtc_minutes= val.min_ones + val.min_tens * 10;
 763     if ((rtc_minutes < real_minutes
 764          ? real_minutes - rtc_minutes
 765          : rtc_minutes - real_minutes) < 30)
 766     {
 767         val.sec_ones = real_seconds % 10;
 768         val.sec_tens = real_seconds / 10;
 769         val.min_ones = real_minutes % 10;
 770         val.min_tens = real_minutes / 10;
 771         mste_write(&val);
 772     }
 773     else
 774         return -1;
 775     return 0;
 776 }
 777 
 778 int atari_set_clock_mmss (unsigned long nowtime)
     /* [previous][next][first][last][top][bottom][index][help] */
 779 {
 780     int retval = 0;
 781     short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 782     unsigned char save_control, save_freq_select, rtc_minutes;
 783 
 784     save_control = RTC_READ (RTC_CONTROL); /* tell the clock it's being set */
 785     RTC_WRITE (RTC_CONTROL, save_control | RTC_SET);
 786 
 787     save_freq_select = RTC_READ (RTC_FREQ_SELECT); /* stop and reset prescaler */
 788     RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2);
 789 
 790     rtc_minutes = RTC_READ (RTC_MINUTES);
 791     if (!(save_control & RTC_DM_BINARY))
 792         BCD_TO_BIN (rtc_minutes);
 793 
 794     /* Since we're only adjusting minutes and seconds, don't interfere
 795        with hour overflow.  This avoids messing with unknown time zones
 796        but requires your RTC not to be off by more than 30 minutes.  */
 797     if ((rtc_minutes < real_minutes
 798          ? real_minutes - rtc_minutes
 799          : rtc_minutes - real_minutes) < 30)
 800         {
 801             if (!(save_control & RTC_DM_BINARY))
 802                 {
 803                     BIN_TO_BCD (real_seconds);
 804                     BIN_TO_BCD (real_minutes);
 805                 }
 806             RTC_WRITE (RTC_SECONDS, real_seconds);
 807             RTC_WRITE (RTC_MINUTES, real_minutes);
 808         }
 809     else
 810         retval = -1;
 811 
 812     RTC_WRITE (RTC_FREQ_SELECT, save_freq_select);
 813     RTC_WRITE (RTC_CONTROL, save_control);
 814     return retval;
 815 }
 816 
 817 
 818 void atari_waitbut (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 819 {
 820     /* sorry, no-op */
 821 }
 822 
 823 
 824 static inline void ata_mfp_out (char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 825 {
 826     while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
 827         barrier ();
 828     mfp.usart_dta = c;
 829 }
 830 
 831 void ata_mfp_print (const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 832 {
 833     for( ; *str; ++str ) {
 834         if (*str == '\n')
 835             ata_mfp_out( '\r' );
 836         ata_mfp_out( *str );
 837     }
 838 }
 839 
 840 static inline void ata_scc_out (char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 841 {
 842     do {
 843         MFPDELAY();
 844     } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
 845     MFPDELAY();
 846     scc.cha_b_data = c;
 847 }
 848 
 849 void ata_scc_print (const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 850 {
 851     for( ; *str; ++str ) {
 852         if (*str == '\n')
 853             ata_scc_out( '\r' );
 854         ata_scc_out( *str );
 855     }
 856 }
 857 
 858 static int ata_par_out (char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 859 {
 860     extern unsigned long loops_per_sec;
 861     unsigned char tmp;
 862     /* This a some-seconds timeout in case no printer is connected */
 863     unsigned long i = loops_per_sec > 1 ? loops_per_sec : 10000000;
 864 
 865     while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
 866         ;
 867     if (!i) return( 0 );
 868     
 869     sound_ym.rd_data_reg_sel = 15;  /* select port B */
 870     sound_ym.wd_data = c;           /* put char onto port */
 871     sound_ym.rd_data_reg_sel = 14;  /* select port A */
 872     tmp = sound_ym.rd_data_reg_sel;
 873     sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
 874     MFPDELAY();                     /* wait a bit */
 875     sound_ym.wd_data = tmp | 0x20;  /* set strobe H */
 876     return( 1 );
 877 }
 878 
 879 void ata_par_print (const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 880 {
 881     static int printer_present = 1;
 882 
 883     if (!printer_present)
 884         return;
 885 
 886     for( ; *str; ++str ) {
 887         if (*str == '\n')
 888             if (!ata_par_out( '\r' )) {
 889                 printer_present = 0;
 890                 return;
 891             }
 892         if (!ata_par_out( *str )) {
 893             printer_present = 0;
 894             return;
 895         }
 896     }
 897 }
 898 
 899 
 900 void atari_debug_init( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 901 {
 902     extern void (*debug_print_proc)(const char *);
 903     extern char m68k_debug_device[];
 904     
 905     if (!strcmp( m68k_debug_device, "ser" )) {
 906         /* defaults to ser2 for a Falcon and ser1 otherwise */
 907         strcpy( m68k_debug_device, 
 908                 ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_FALCON) ?
 909                 "ser2" : "ser1" );
 910 
 911     }
 912 
 913     if (!strcmp( m68k_debug_device, "ser1" )) {
 914         /* ST-MFP Modem1 serial port */
 915         mfp.trn_stat  &= ~0x01; /* disable TX */
 916         mfp.usart_ctr  = 0x88;  /* clk 1:16, 8N1 */
 917         mfp.tim_ct_cd &= 0x70;  /* stop timer D */
 918         mfp.tim_dt_d   = 2;     /* 9600 bps */
 919         mfp.tim_ct_cd |= 0x01;  /* start timer D, 1:4 */
 920         mfp.trn_stat  |= 0x01;  /* enable TX */
 921         debug_print_proc = ata_mfp_print;
 922     }
 923     else if (!strcmp( m68k_debug_device, "ser2" )) {
 924         /* SCC Modem2 serial port */
 925         static unsigned char *p, scc_table[] = {
 926             9, 12,              /* Reset */
 927             4, 0x44,            /* x16, 1 stopbit, no parity */
 928             3, 0xc0,            /* receiver: 8 bpc */
 929             5, 0xe2,            /* transmitter: 8 bpc, assert dtr/rts */
 930             9, 0,               /* no interrupts */
 931             10, 0,              /* NRZ */
 932             11, 0x50,           /* use baud rate generator */
 933             12, 24, 13, 0,      /* 9600 baud */
 934             14, 2, 14, 3,       /* use master clock for BRG, enable */
 935             3, 0xc1,            /* enable receiver */
 936             5, 0xea,            /* enable transmitter */
 937             0
 938         };
 939             
 940         (void)scc.cha_b_ctrl; /* reset reg pointer */
 941         for( p = scc_table; *p != 0; ) {
 942             scc.cha_b_ctrl = *p++;
 943             MFPDELAY();
 944             scc.cha_b_ctrl = *p++;
 945             MFPDELAY();
 946         }
 947         debug_print_proc = ata_scc_print;
 948     }
 949     else if (!strcmp( m68k_debug_device, "par" )) {
 950         /* parallel printer */
 951         atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
 952         sound_ym.rd_data_reg_sel = 7;  /* select mixer control */
 953         sound_ym.wd_data = 0xff;       /* sound off, ports are output */
 954         sound_ym.rd_data_reg_sel = 15; /* select port B */
 955         sound_ym.wd_data = 0;          /* no char */
 956         sound_ym.rd_data_reg_sel = 14; /* select port A */
 957         sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
 958         debug_print_proc = ata_par_print;
 959     }
 960     else
 961         debug_print_proc = NULL;
 962 }
 963 
 964 
 965 void ata_serial_print (const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 966 {
 967   int c;
 968 
 969   while (c = *str++, c != 0)
 970     {
 971       if (c == '\n')
 972         {
 973           while (!(mfp.trn_stat & (1 << 7)))
 974             barrier ();
 975           mfp.usart_dta = '\r';
 976         }
 977       while (!(mfp.trn_stat & (1 << 7)))
 978         barrier ();
 979       mfp.usart_dta = c;
 980     }
 981 }
 982 
 983 /* ++roman:
 984  *
 985  * This function does a reset on machines that lack the ability to
 986  * assert the processor's _RESET signal somehow via hardware. It is
 987  * based on the fact that you can find the initial SP and PC values
 988  * after a reset at physical addresses 0 and 4. This works pretty well
 989  * for Atari machines, since the lowest 8 bytes of physical memory are
 990  * really ROM (mapped by hardware). For other 680x0 machines: don't
 991  * know if it works...
 992  *
 993  * To get the values at addresses 0 and 4, the MMU better is turned
 994  * off first. After that, we have to jump into physical address space
 995  * (the PC before the pmove statement points to the virtual address of
 996  * the code). Getting that physical address is not hard, but the code
 997  * becomes a bit complex since I've tried to ensure that the jump
 998  * statement after the pmove is in the cache already (otherwise the
 999  * processor can't fetch it!). For that, the code first jumps to the
1000  * jump statement with the (virtual) address of the pmove section in
1001  * an address register . The jump statement is surely in the cache
1002  * now. After that, that physical address of the reset code is loaded
1003  * into the same address register, pmove is done and the same jump
1004  * statements goes to the reset code. Since there are not many
1005  * statements between the two jumps, I hope it stays in the cache.
1006  *
1007  * The C code makes heavy use of the GCC features that you can get the
1008  * address of a C label. No hope to compile this with another compiler
1009  * than GCC!
1010  */
1011   
1012 /* ++andreas: no need for complicated code, just depend on prefetch */
1013 
1014 void atari_reset (void)
     /* [previous][next][first][last][top][bottom][index][help] */
1015 {
1016     long tc_val = 0;
1017     long reset_addr;
1018 
1019     /* On the Medusa, phys. 0x4 may contain garbage because it's no
1020        ROM.  See above for explanation why we cannot use PTOV(4). */
1021     reset_addr = is_medusa ? 0xe00030 : *(unsigned long *) 0xff000004;
1022 
1023     acia.key_ctrl = ACIA_RESET;             /* reset ACIA for switch off OverScan, if it's active */
1024 
1025     /* processor independent: turn off interrupts and reset the VBR;
1026      * the caches must be left enabled, else prefetching the final jump
1027      * instruction doesn't work. */
1028     cli();
1029     __asm__ __volatile__
1030         ("moveq #0,%/d0\n\t"
1031          "movec %/d0,%/vbr"
1032          : : : "d0" );
1033     
1034     if (m68k_is040or060) {
1035         unsigned long jmp_addr040 = VTOP(&&jmp_addr_label040);
1036         if (m68k_is040or060 == 6) {
1037             /* 68060: clear PCR to turn off superscalar operation */
1038             __asm__ __volatile__
1039                 ("moveq #0,%/d0\n\t"
1040                  ".long 0x4e7b0808"     /* movec d0,pcr */
1041                  : : : "d0" );
1042         }
1043             
1044         __asm__ __volatile__
1045             ("movel    %0,%/d0\n\t"
1046              "andl     #0xff000000,%/d0\n\t"
1047              "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
1048              ".long    0x4e7b0004\n\t"   /* movec d0,itt0 */
1049              ".long    0x4e7b0006\n\t"   /* movec d0,dtt0 */
1050              "jmp   %0@\n\t"
1051              : /* no outputs */
1052              : "a" (jmp_addr040)
1053              : "d0" );
1054       jmp_addr_label040:
1055         __asm__ __volatile__
1056           ("moveq #0,%/d0\n\t"
1057            ".word 0xf4d8\n\t"           /* cinva i/d */
1058            ".word 0xf518\n\t"           /* pflusha */
1059            ".long 0x4e7b0003\n\t"       /* movec d0,tc */
1060            "jmp %0@"
1061            : /* no outputs */
1062            : "a" (reset_addr)
1063            : "d0");
1064     }
1065     else
1066         __asm__ __volatile__
1067             ("pmove %0@,%/tc\n\t"
1068              "jmp %1@"
1069              : /* no outputs */
1070              : "a" (&tc_val), "a" (reset_addr));
1071 }
1072 
1073 
1074 void atari_get_model(char *model)
     /* [previous][next][first][last][top][bottom][index][help] */
1075 {
1076     strcpy(model, "Atari ");
1077     switch (boot_info.bi_atari.mch_cookie >> 16) {
1078         case ATARI_MCH_ST:
1079             if (ATARIHW_PRESENT(MSTE_CLK))
1080                 strcat (model, "Mega ST");
1081             else
1082                 strcat (model, "ST");
1083             break;
1084         case ATARI_MCH_STE:
1085             if ((boot_info.bi_atari.mch_cookie & 0xffff) == 0x10)
1086                 strcat (model, "Mega STE");
1087             else
1088                 strcat (model, "STE");
1089             break;
1090         case ATARI_MCH_TT:
1091             if (is_medusa)
1092                 /* Medusa has TT _MCH cookie */
1093                 strcat (model, "Medusa");
1094             else
1095                 strcat (model, "TT");
1096             break;
1097         case ATARI_MCH_FALCON:
1098             strcat (model, "Falcon");
1099             break;
1100         default:
1101             sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
1102                      boot_info.bi_atari.mch_cookie);
1103             break;
1104     }
1105 }
1106 
1107 
1108 int atari_get_hardware_list(char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
1109 {
1110     int len = 0, i;
1111 
1112     for (i = 0; i < boot_info.num_memory; i++)
1113         len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
1114                         boot_info.memory[i].size >> 20,
1115                         boot_info.memory[i].addr,
1116                         (boot_info.memory[i].addr & 0xff000000 ?
1117                          "alternate RAM" : "ST-RAM"));
1118 
1119 #define ATARIHW_ANNOUNCE(name,str)                              \
1120     if (ATARIHW_PRESENT(name))                  \
1121         len += sprintf (buffer + len, "\t%s\n", str)
1122 
1123     len += sprintf (buffer + len, "Detected hardware:\n");
1124     ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
1125     ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
1126     ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
1127     ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
1128     ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
1129     ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
1130     ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
1131     ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
1132     ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
1133     ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
1134     ATARIHW_ANNOUNCE(IDE, "IDE Interface");
1135     ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
1136     ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
1137     ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
1138     ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
1139     ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
1140     ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
1141     ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
1142     ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
1143     ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
1144     ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
1145     ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
1146     ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
1147     ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
1148     ATARIHW_ANNOUNCE(SCU, "System Control Unit");
1149     ATARIHW_ANNOUNCE(BLITTER, "Blitter");
1150     ATARIHW_ANNOUNCE(VME, "VME Bus");
1151 
1152     return(len);
1153 }

/* [previous][next][first][last][top][bottom][index][help] */