root/arch/m68k/amiga/config.c

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

DEFINITIONS

This source file includes following definitions.
  1. config_amiga
  2. timer_wrapper
  3. amiga_sched_init
  4. amiga_gettimeoffset
  5. a3000_gettod
  6. a2000_gettod
  7. amiga_hwclk
  8. amiga_set_clock_mmss
  9. amiga_waitbut
  10. ami_serial_print
  11. amiga_debug_init
  12. dbprintf
  13. amiga_reset
  14. ami_savekmsg_init
  15. ami_mem_print
  16. amiga_get_model
  17. amiga_get_hardware_list

   1 /*
   2  *  linux/amiga/config.c
   3  *
   4  *  Copyright (C) 1993 Hamish Macdonald
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file README.legal in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 /*
  12  * Miscellaneous Amiga stuff
  13  */
  14 
  15 #include <stdarg.h>
  16 #include <linux/config.h>
  17 #include <linux/types.h>
  18 #include <linux/kernel.h>
  19 #include <linux/mm.h>
  20 #include <linux/kd.h>
  21 #include <linux/tty.h>
  22 #include <linux/console.h>
  23 #include <linux/linkage.h>
  24 
  25 #include <asm/system.h>
  26 #include <asm/pgtable.h>
  27 #include <asm/bootinfo.h>
  28 #include <asm/amigahw.h>
  29 #include <asm/amigaints.h>
  30 #include <asm/irq.h>
  31 #include <asm/machdep.h>
  32 
  33 u_long amiga_masterclock;
  34 u_long amiga_colorclock;
  35 
  36 extern char m68k_debug_device[];
  37 
  38 extern void amiga_sched_init(isrfunc handler);
  39 extern int amiga_keyb_init(void);
  40 extern int amiga_kbdrate (struct kbd_repeat *);
  41 extern void amiga_init_INTS (void);
  42 extern int amiga_add_isr (unsigned long, isrfunc, int, void *, char *);
  43 extern int amiga_remove_isr (unsigned long, isrfunc);
  44 extern int amiga_get_irq_list (char *, int);
  45 extern void amiga_enable_irq(unsigned int);
  46 extern void amiga_disable_irq(unsigned int);
  47 extern unsigned long amiga_gettimeoffset (void);
  48 extern void a3000_gettod (int *, int *, int *, int *, int *, int *);
  49 extern void a2000_gettod (int *, int *, int *, int *, int *, int *);
  50 extern int amiga_hwclk (int, struct hwclk_time *);
  51 extern int amiga_set_clock_mmss (unsigned long);
  52 extern void amiga_check_partition (struct gendisk *hd, unsigned int dev);
  53 extern void amiga_mksound( unsigned int count, unsigned int ticks );
  54 #ifdef CONFIG_BLK_DEV_FD
  55 extern int amiga_floppy_init (void);
  56 extern void amiga_floppy_setup(char *, int *);
  57 #endif
  58 extern void amiga_reset (void);
  59 extern void amiga_waitbut(void);
  60 extern struct consw fb_con;
  61 extern struct fb_info *amiga_fb_init(long *);
  62 extern void zorro_init(void);
  63 static void ami_savekmsg_init(void);
  64 static void ami_mem_print(const char *b);
  65 extern void amiga_debug_init(void);
  66 extern void amiga_video_setup(char *, int *);
  67 
  68 extern void (*kd_mksound)(unsigned int, unsigned int);
  69 
  70 void config_amiga(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72   char *type = NULL;
  73 
  74   switch(boot_info.bi_amiga.model) {
  75   case AMI_500:
  76     type = "A500";
  77     break;
  78   case AMI_500PLUS:
  79     type = "A500+";
  80     break;
  81   case AMI_600:
  82     type = "A600";
  83     break;
  84   case AMI_1000:
  85     type = "A1000";
  86     break;
  87   case AMI_1200:
  88     type = "A1200";
  89     break;
  90   case AMI_2000:
  91     type = "A2000";
  92     break;
  93   case AMI_2500:
  94     type = "A2500";
  95     break;
  96   case AMI_3000:
  97     type = "A3000";
  98     break;
  99   case AMI_3000T:
 100     type = "A3000T";
 101     break;
 102   case AMI_3000PLUS:
 103     type = "A3000+";
 104     break;
 105   case AMI_4000:
 106     type = "A4000";
 107     break;
 108   case AMI_4000T:
 109     type = "A4000T";
 110     break;
 111   case AMI_CDTV:
 112     type = "CDTV";
 113     break;
 114   case AMI_CD32:
 115     type = "CD32";
 116     break;
 117   case AMI_DRACO:
 118     type = "Draco";
 119     break;
 120   }
 121   printk("Amiga hardware found: ");
 122   if (type)
 123     printk("[%s] ", type);
 124   switch(boot_info.bi_amiga.model) {
 125   case AMI_UNKNOWN:
 126     goto Generic;
 127 
 128   case AMI_500:
 129   case AMI_500PLUS:
 130   case AMI_1000:
 131     AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
 132     printk("A2000_CLK ");
 133     goto Generic;
 134 
 135   case AMI_600:
 136   case AMI_1200:
 137     AMIGAHW_SET(A1200_IDE);
 138     printk("A1200_IDE ");
 139     AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
 140     printk("A2000_CLK ");
 141     goto Generic;
 142 
 143   case AMI_2000:
 144   case AMI_2500:
 145     AMIGAHW_SET(A2000_CLK);
 146     printk("A2000_CLK ");
 147     goto Generic;
 148 
 149   case AMI_3000:
 150   case AMI_3000T:
 151     AMIGAHW_SET(AMBER_FF);
 152     printk("AMBER_FF ");
 153     AMIGAHW_SET(MAGIC_REKICK);
 154     printk("MAGIC_REKICK ");
 155     /* fall through */
 156   case AMI_3000PLUS:
 157     AMIGAHW_SET(A3000_SCSI);
 158     printk("A3000_SCSI ");
 159     AMIGAHW_SET(A3000_CLK);
 160     printk("A3000_CLK ");
 161     goto Generic;
 162 
 163   case AMI_4000T:
 164     AMIGAHW_SET(A4000_SCSI);
 165     printk("A4000_SCSI ");
 166     /* fall through */
 167   case AMI_4000:
 168     AMIGAHW_SET(A4000_IDE);
 169     printk("A4000_IDE ");
 170     AMIGAHW_SET(A3000_CLK);
 171     printk("A3000_CLK ");
 172     goto Generic;
 173 
 174   case AMI_CDTV:
 175   case AMI_CD32:
 176     AMIGAHW_SET(CD_ROM);
 177     printk("CD_ROM ");
 178     AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
 179     printk("A2000_CLK ");
 180     goto Generic;
 181 
 182   Generic:
 183     AMIGAHW_SET(AMI_VIDEO);
 184     AMIGAHW_SET(AMI_BLITTER);
 185     AMIGAHW_SET(AMI_AUDIO);
 186     AMIGAHW_SET(AMI_FLOPPY);
 187     AMIGAHW_SET(AMI_KEYBOARD);
 188     AMIGAHW_SET(AMI_MOUSE);
 189     AMIGAHW_SET(AMI_SERIAL);
 190     AMIGAHW_SET(AMI_PARALLEL);
 191     AMIGAHW_SET(CHIP_RAM);
 192     AMIGAHW_SET(PAULA);
 193     printk("VIDEO BLITTER AUDIO FLOPPY KEYBOARD MOUSE SERIAL PARALLEL "
 194            "CHIP_RAM PAULA ");
 195 
 196     switch(boot_info.bi_amiga.chipset) {
 197     case CS_OCS:
 198     case CS_ECS:
 199     case CS_AGA:
 200       switch (custom.deniseid & 0xf) {
 201       case 0x0c:
 202         AMIGAHW_SET(DENISE_HR);
 203         printk("DENISE_HR");
 204         break;
 205       case 0x08:
 206         AMIGAHW_SET(LISA);
 207         printk("LISA ");
 208         break;
 209       }
 210       break;
 211     default:
 212       AMIGAHW_SET(DENISE);
 213       printk("DENISE ");
 214       break;
 215     }
 216     switch ((custom.vposr>>8) & 0x7f) {
 217     case 0x00:
 218       AMIGAHW_SET(AGNUS_PAL);
 219       printk("AGNUS_PAL ");
 220       break;
 221     case 0x10:
 222       AMIGAHW_SET(AGNUS_NTSC);
 223       printk("AGNUS_NTSC ");
 224       break;
 225     case 0x20:
 226     case 0x21:
 227       AMIGAHW_SET(AGNUS_HR_PAL);
 228       printk("AGNUS_HR_PAL ");
 229       break;
 230     case 0x30:
 231     case 0x31:
 232       AMIGAHW_SET(AGNUS_HR_NTSC);
 233       printk("AGNUS_HR_NTSC ");
 234       break;
 235     case 0x22:
 236     case 0x23:
 237       AMIGAHW_SET(ALICE_PAL);
 238       printk("ALICE_PAL ");
 239       break;
 240     case 0x32:
 241     case 0x33:
 242       AMIGAHW_SET(ALICE_NTSC);
 243       printk("ALICE_NTSC ");
 244       break;
 245     }
 246     AMIGAHW_SET(ZORRO);
 247     printk("ZORRO ");
 248     break;
 249 
 250   case AMI_DRACO:
 251     panic("No support for Draco yet");
 252  
 253   default:
 254     panic("Unknown Amiga Model");
 255   }
 256   printk("\n");
 257  
 258   mach_sched_init      = amiga_sched_init;
 259   mach_keyb_init       = amiga_keyb_init;
 260   mach_kbdrate         = amiga_kbdrate;
 261   mach_init_INTS       = amiga_init_INTS;
 262   mach_add_isr         = amiga_add_isr;
 263 #if 0 /* ++1.3++ */
 264   mach_remove_isr      = amiga_remove_isr;
 265   mach_enable_irq      = amiga_enable_irq;
 266   mach_disable_irq     = amiga_disable_irq;
 267 #endif
 268   mach_get_irq_list    = amiga_get_irq_list;
 269   mach_gettimeoffset   = amiga_gettimeoffset;
 270   if (AMIGAHW_PRESENT(A3000_CLK)){
 271     mach_gettod  = a3000_gettod;
 272     mach_max_dma_address = 0xffffffff; /*
 273                                         * default MAX_DMA 0xffffffff
 274                                         * on Z3 machines - we should
 275                                         * consider adding something
 276                                         * like a dma_mask in kmalloc
 277                                         * later on, so people using Z2
 278                                         * boards in Z3 machines won't
 279                                         * get into trouble - Jes
 280                                         */
 281   }
 282   else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
 283     mach_gettod  = a2000_gettod;
 284     mach_max_dma_address = 0x00ffffff; /*
 285                                         * default MAX_DMA 0x00ffffff
 286                                         * on Z2 machines.
 287                                         */
 288   }
 289   mach_hwclk           = amiga_hwclk;
 290   mach_set_clock_mmss  = amiga_set_clock_mmss;
 291   mach_check_partition = amiga_check_partition;
 292   mach_mksound         = amiga_mksound;
 293 #ifdef CONFIG_BLK_DEV_FD
 294   mach_floppy_init     = amiga_floppy_init;
 295   mach_floppy_setup    = amiga_floppy_setup;
 296 #endif
 297   mach_reset           = amiga_reset;
 298   waitbut              = amiga_waitbut;
 299   conswitchp           = &fb_con;
 300   mach_fb_init         = amiga_fb_init;
 301   mach_debug_init      = amiga_debug_init;
 302   mach_video_setup     = amiga_video_setup;
 303   kd_mksound           = amiga_mksound;
 304 
 305   /* Fill in the clock values (based on the 700 kHz E-Clock) */
 306   amiga_masterclock = 40*amiga_eclock;  /* 28 MHz */
 307   amiga_colorclock = 5*amiga_eclock;            /* 3.5 MHz */
 308 
 309   /* clear all DMA bits */
 310   custom.dmacon = DMAF_ALL;
 311   /* ensure that the DMA master bit is set */
 312   custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
 313 
 314   /* initialize chipram allocator */
 315   amiga_chip_init ();
 316 
 317   /* initialize only once here, not every time the debug level is raised */
 318   if (!strcmp( m68k_debug_device, "mem" ))
 319     ami_savekmsg_init();
 320 
 321   /*
 322    * if it is an A3000, set the magic bit that forces
 323    * a hard rekick
 324    */
 325   if (AMIGAHW_PRESENT(MAGIC_REKICK))
 326     *(u_char *)ZTWO_VADDR(0xde0002) |= 0x80;
 327 
 328   zorro_init();
 329 #ifdef CONFIG_ZORRO
 330   /*
 331    * Identify all known AutoConfig Expansion Devices
 332    */
 333   zorro_identify();
 334 #endif /* CONFIG_ZORRO */
 335 }
 336 
 337 extern long time_finetune;      /* from kernel/sched.c */
 338 
 339 static unsigned short jiffy_ticks;
 340 
 341 #if 1 /* ++1.3++ */
 342 static void timer_wrapper( int irq, struct pt_regs *fp, void *otimerf )
     /* [previous][next][first][last][top][bottom][index][help] */
 343  {
 344    unsigned short flags, old_flags;
 345 
 346    ciab.icr = 0x01;
 347 
 348    save_flags(flags);
 349    old_flags = (flags & ~0x0700) | (fp->sr & 0x0700);
 350    
 351    restore_flags(old_flags);
 352 
 353    (*(isrfunc)otimerf)( irq, fp, NULL );
 354 
 355    restore_flags(flags);
 356    ciab.icr = 0x81;
 357 }
 358 #endif
 359 
 360 void amiga_sched_init (isrfunc timer_routine)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362 
 363 #if 0 /* XXX */ /* I think finetune was removed by the 1.3.29 patch */
 364     double finetune;
 365 #endif
 366 
 367     jiffy_ticks = (amiga_eclock+50)/100;
 368 #if 0 /* XXX */
 369     finetune = (jiffy_ticks-amiga_eclock/HZ)/amiga_eclock*1000000*(1<<24);
 370     time_finetune = finetune+0.5;
 371 #endif
 372 
 373     ciab.cra &= 0xC0;    /* turn off timer A, continous mode, from Eclk */
 374     ciab.talo = jiffy_ticks % 256;
 375     ciab.tahi = jiffy_ticks / 256;
 376     /* CIA interrupts when counter underflows, so adjust ticks by 1 */
 377     jiffy_ticks -= 1;
 378 
 379     /* install interrupt service routine for CIAB Timer A */
 380     /*
 381      * Please don't change this to use ciaa, as it interfers with the
 382      * SCSI code. We'll have to take a look at this later
 383      */
 384 #if 0
 385     add_isr (IRQ_AMIGA_CIAB_TA, timer_routine, 0, NULL, "timer");
 386 #else
 387     add_isr (IRQ_AMIGA_CIAB_TA, timer_wrapper, 0, timer_routine, "timer");
 388 #endif
 389     /* start timer */
 390     ciab.cra |= 0x01;
 391 }
 392 
 393 #define TICK_SIZE 10000
 394 
 395 /* This is always executed with interrupts disabled.  */
 396 unsigned long amiga_gettimeoffset (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 397 {
 398     unsigned short hi, lo, hi2;
 399     unsigned long ticks, offset = 0;
 400 
 401     /* read CIA A timer A current value */
 402     hi  = ciab.tahi;
 403     lo  = ciab.talo;
 404     hi2 = ciab.tahi;
 405 
 406     if (hi != hi2) {
 407         lo = ciab.talo;
 408         hi = hi2;
 409     }
 410 
 411     ticks = hi << 8 | lo;
 412 
 413 #if 0 /* XXX */
 414 /* reading the ICR clears all interrupts.  bad idea! */
 415       if (ticks > jiffy_ticks - jiffy_ticks / 100)
 416         /* check for pending interrupt */
 417         if (ciab.icr & CIA_ICR_TA)
 418           offset = 10000;
 419 #endif
 420 
 421     ticks = (jiffy_ticks-1) - ticks;
 422     ticks = (10000 * ticks) / jiffy_ticks;
 423 
 424     return ticks + offset;
 425 }
 426 
 427 void a3000_gettod (int *yearp, int *monp, int *dayp,
     /* [previous][next][first][last][top][bottom][index][help] */
 428                    int *hourp, int *minp, int *secp)
 429 {
 430         volatile struct tod3000 *tod = TOD_3000;
 431 
 432         tod->cntrl1 = TOD3000_CNTRL1_HOLD;
 433 
 434         *secp  = tod->second1 * 10 + tod->second2;
 435         *minp  = tod->minute1 * 10 + tod->minute2;
 436         *hourp = tod->hour1   * 10 + tod->hour2;
 437         *dayp  = tod->day1    * 10 + tod->day2;
 438         *monp  = tod->month1  * 10 + tod->month2;
 439         *yearp = tod->year1   * 10 + tod->year2;
 440 
 441         tod->cntrl1 = TOD3000_CNTRL1_FREE;
 442 }
 443 
 444 void a2000_gettod (int *yearp, int *monp, int *dayp,
     /* [previous][next][first][last][top][bottom][index][help] */
 445                    int *hourp, int *minp, int *secp)
 446 {
 447         volatile struct tod2000 *tod = TOD_2000;
 448 
 449         tod->cntrl1 = TOD2000_CNTRL1_HOLD;
 450 
 451         while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
 452                 ;
 453 
 454         *secp  = tod->second1     * 10 + tod->second2;
 455         *minp  = tod->minute1     * 10 + tod->minute2;
 456         *hourp = (tod->hour1 & 3) * 10 + tod->hour2;
 457         *dayp  = tod->day1        * 10 + tod->day2;
 458         *monp  = tod->month1      * 10 + tod->month2;
 459         *yearp = tod->year1       * 10 + tod->year2;
 460 
 461         if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE))
 462                 if ((!tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12)
 463                         *hourp = 0;
 464                 else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12)
 465                         *hourp += 12;
 466 
 467         tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 468 }
 469 
 470 int amiga_hwclk(int op, struct hwclk_time *t)
     /* [previous][next][first][last][top][bottom][index][help] */
 471 {
 472         if (AMIGAHW_PRESENT(A3000_CLK)) {
 473                 volatile struct tod3000 *tod = TOD_3000;
 474 
 475                 tod->cntrl1 = TOD3000_CNTRL1_HOLD;
 476 
 477                 if (!op) { /* read */
 478                         t->sec  = tod->second1 * 10 + tod->second2;
 479                         t->min  = tod->minute1 * 10 + tod->minute2;
 480                         t->hour = tod->hour1   * 10 + tod->hour2;
 481                         t->day  = tod->day1    * 10 + tod->day2;
 482                         t->wday = tod->weekday;
 483                         t->mon  = tod->month1  * 10 + tod->month2 - 1;
 484                         t->year = tod->year1   * 10 + tod->year2;
 485                 } else {
 486                         tod->second1 = t->sec / 10;
 487                         tod->second2 = t->sec % 10;
 488                         tod->minute1 = t->min / 10;
 489                         tod->minute2 = t->min % 10;
 490                         tod->hour1   = t->hour / 10;
 491                         tod->hour2   = t->hour % 10;
 492                         tod->day1    = t->day / 10;
 493                         tod->day2    = t->day % 10;
 494                         if (t->wday != -1)
 495                                 tod->weekday = t->wday;
 496                         tod->month1  = (t->mon + 1) / 10;
 497                         tod->month2  = (t->mon + 1) % 10;
 498                         tod->year1   = t->year / 10;
 499                         tod->year2   = t->year % 10;
 500                 }
 501 
 502                 tod->cntrl1 = TOD3000_CNTRL1_FREE;
 503         } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
 504                 volatile struct tod2000 *tod = TOD_2000;
 505 
 506                 tod->cntrl1 = TOD2000_CNTRL1_HOLD;
 507             
 508                 while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
 509                         ;
 510 
 511                 if (!op) { /* read */
 512                         t->sec  = tod->second1     * 10 + tod->second2;
 513                         t->min  = tod->minute1     * 10 + tod->minute2;
 514                         t->hour = (tod->hour1 & 3) * 10 + tod->hour2;
 515                         t->day  = tod->day1        * 10 + tod->day2;
 516                         t->wday = tod->weekday;
 517                         t->mon  = tod->month1      * 10 + tod->month2 - 1;
 518                         t->year = tod->year1       * 10 + tod->year2;
 519 
 520                         if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE))
 521                                 if ((!tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12)
 522                                         t->hour = 0;
 523                                 else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12)
 524                                         t->hour += 12;
 525                 } else {
 526                         tod->second1 = t->sec / 10;
 527                         tod->second2 = t->sec % 10;
 528                         tod->minute1 = t->min / 10;
 529                         tod->minute2 = t->min % 10;
 530                         if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE)
 531                                 tod->hour1 = t->hour / 10;
 532                         else if (t->hour >= 12)
 533                                 tod->hour1 = TOD2000_HOUR1_PM +
 534                                         (t->hour - 12) / 10;
 535                         else
 536                                 tod->hour1 = t->hour / 10;
 537                         tod->hour2   = t->hour % 10;
 538                         tod->day1    = t->day / 10;
 539                         tod->day2    = t->day % 10;
 540                         if (t->wday != -1)
 541                                 tod->weekday = t->wday;
 542                         tod->month1  = (t->mon + 1) / 10;
 543                         tod->month2  = (t->mon + 1) % 10;
 544                         tod->year1   = t->year / 10;
 545                         tod->year2   = t->year % 10;
 546                 }
 547 
 548                 tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 549         }
 550 
 551         return 0;
 552 }
 553 
 554 int amiga_set_clock_mmss (unsigned long nowtime)
     /* [previous][next][first][last][top][bottom][index][help] */
 555 {
 556         short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 557 
 558         if (AMIGAHW_PRESENT(A3000_CLK)) {
 559                 volatile struct tod3000 *tod = TOD_3000;
 560 
 561                 tod->cntrl1 = TOD3000_CNTRL1_HOLD;
 562 
 563                 tod->second1 = real_seconds / 10;
 564                 tod->second2 = real_seconds % 10;
 565                 tod->minute1 = real_minutes / 10;
 566                 tod->minute2 = real_minutes % 10;
 567                 
 568                 tod->cntrl1 = TOD3000_CNTRL1_FREE;
 569         } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
 570                 volatile struct tod2000 *tod = TOD_2000;
 571 
 572                 tod->cntrl1 = TOD2000_CNTRL1_HOLD;
 573             
 574                 while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
 575                         ;
 576 
 577                 tod->second1 = real_seconds / 10;
 578                 tod->second2 = real_seconds % 10;
 579                 tod->minute1 = real_minutes / 10;
 580                 tod->minute2 = real_minutes % 10;
 581 
 582                 tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 583         }
 584 
 585         return 0;
 586 }
 587 
 588 void amiga_waitbut (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 589 {
 590     int i;
 591 
 592     while (1) {
 593         while (ciaa.pra & 0x40);
 594 
 595         /* debounce */
 596         for (i = 0; i < 1000; i++);
 597 
 598         if (!(ciaa.pra & 0x40))
 599             break;
 600     }
 601 
 602     /* wait for button up */
 603     while (1) {
 604         while (!(ciaa.pra & 0x40));
 605 
 606         /* debounce */
 607         for (i = 0; i < 1000; i++);
 608 
 609         if (ciaa.pra & 0x40)
 610             break;
 611     }
 612 }
 613 
 614 void ami_serial_print (const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 615 {
 616     while (*str) {
 617         if (*str == '\n') {
 618             custom.serdat = (unsigned char)'\r' | 0x100;
 619             while (!(custom.serdatr & 0x2000))
 620                 ;
 621         }
 622         custom.serdat = (unsigned char)*str++ | 0x100;
 623         while (!(custom.serdatr & 0x2000))
 624             ;
 625     }
 626 }
 627 
 628 void amiga_debug_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 629 {
 630     extern void (*debug_print_proc)(const char *);
 631 
 632     if (!strcmp( m68k_debug_device, "ser" )) {
 633         /* no initialization required (?) */
 634         debug_print_proc = ami_serial_print;
 635     } else if (!strcmp( m68k_debug_device, "mem" )) {
 636         /* already initialized by config_amiga() (needed only once) */
 637         debug_print_proc = ami_mem_print;
 638     }
 639 }
 640 
 641 void dbprintf(const char *fmt , ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 642 {
 643         static char buf[1024];
 644         va_list args;
 645         extern void console_print (const char *str);
 646         extern int vsprintf(char * buf, const char * fmt, va_list args);
 647 
 648         va_start(args, fmt);
 649         vsprintf(buf, fmt, args);
 650         va_end(args);
 651 
 652         console_print (buf);
 653 }
 654 
 655 NORET_TYPE void amiga_reset( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 656     ATTRIB_NORET;
 657 
 658 void amiga_reset (void)
 659 {
 660   unsigned long jmp_addr040 = VTOP(&&jmp_addr_label040);
 661   unsigned long jmp_addr = VTOP(&&jmp_addr_label);
 662 
 663   cli();
 664   if (m68k_is040or060)
 665     /* Setup transparent translation registers for mapping
 666      * of 16 MB kernel segment before disabling translation
 667      */
 668     __asm__ __volatile__
 669       ("movel    %0,%/d0\n\t"
 670        "andl     #0xff000000,%/d0\n\t"
 671        "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
 672        ".long    0x4e7b0004\n\t"   /* movec d0,itt0 */
 673        ".long    0x4e7b0006\n\t"   /* movec d0,dtt0 */
 674        "jmp      %0@\n\t"
 675        : /* no outputs */
 676        : "a" (jmp_addr040));
 677   else
 678     /* for 680[23]0, just disable translation and jump to the physical
 679      * address of the label
 680      */
 681     __asm__ __volatile__
 682       ("pmove  %/tc,%@\n\t"
 683        "bclr   #7,%@\n\t"
 684        "pmove  %@,%/tc\n\t"
 685        "jmp    %0@\n\t"
 686        : /* no outputs */
 687        : "a" (jmp_addr));
 688  jmp_addr_label040:
 689   /* disable translation on '040 now */
 690   __asm__ __volatile__    
 691     ("moveq #0,%/d0\n\t"
 692      ".long 0x4e7b0003\n\t"         /* movec d0,tc; disable MMU */
 693      : /* no outputs */
 694      : /* no inputs */
 695      : "d0");
 696 
 697  jmp_addr_label:
 698   /* pickup reset address from AmigaOS ROM, reset devices and jump
 699    * to reset address
 700    */
 701   __asm__ __volatile__
 702     ("movew #0x2700,%/sr\n\t"
 703      "leal  0x01000000,%/a0\n\t"
 704      "subl  %/a0@(-0x14),%/a0\n\t"
 705      "movel %/a0@(4),%/a0\n\t"
 706      "subql #2,%/a0\n\t"
 707      "bra   1f\n\t"
 708      /* align on a longword boundary */
 709      __ALIGN_STR "\n"
 710      "1:\n\t"
 711      "reset\n\t"
 712      "jmp   %/a0@" : /* Just that gcc scans it for % escapes */ );
 713   
 714   for (;;);
 715 
 716 }
 717 
 718 extern void *amiga_chip_alloc(long size);
 719 
 720 
 721 #define SAVEKMSG_MAXMEM         128*1024
 722 
 723 
 724 #define SAVEKMSG_MAGIC1         0x53415645      /* 'SAVE' */
 725 #define SAVEKMSG_MAGIC2         0x4B4D5347      /* 'KMSG' */
 726 
 727 struct savekmsg {
 728     u_long magic1;              /* SAVEKMSG_MAGIC1 */
 729     u_long magic2;              /* SAVEKMSG_MAGIC2 */
 730     u_long magicptr;            /* address of magic1 */
 731     u_long size;
 732     char data[0];
 733 };
 734 
 735 static struct savekmsg *savekmsg = NULL;
 736 
 737 
 738 static void ami_savekmsg_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 739 {
 740     savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
 741     savekmsg->magic1 = SAVEKMSG_MAGIC1;
 742     savekmsg->magic2 = SAVEKMSG_MAGIC2;
 743     savekmsg->magicptr = VTOP(savekmsg);
 744     savekmsg->size = 0;
 745 }
 746 
 747 
 748 static void ami_mem_print(const char *b)
     /* [previous][next][first][last][top][bottom][index][help] */
 749 {
 750     int len;
 751 
 752     for (len = 0; b[len]; len++);
 753     if (savekmsg->size+len <= SAVEKMSG_MAXMEM) {
 754         memcpy(savekmsg->data+savekmsg->size, b, len);
 755         savekmsg->size += len;
 756     }
 757 }
 758 
 759 
 760 void amiga_get_model(char *model)
     /* [previous][next][first][last][top][bottom][index][help] */
 761 {
 762     strcpy(model, "Amiga ");
 763     switch (boot_info.bi_amiga.model) {
 764         case AMI_500:
 765             strcat(model, "500");
 766             break;
 767         case AMI_500PLUS:
 768             strcat(model, "500+");
 769             break;
 770         case AMI_600:
 771             strcat(model, "600");
 772             break;
 773         case AMI_1000:
 774             strcat(model, "1000");
 775             break;
 776         case AMI_1200:
 777             strcat(model, "1200");
 778             break;
 779         case AMI_2000:
 780             strcat(model, "2000");
 781             break;
 782         case AMI_2500:
 783             strcat(model, "2500");
 784             break;
 785         case AMI_3000:
 786             strcat(model, "3000");
 787             break;
 788         case AMI_3000T:
 789             strcat(model, "3000T");
 790             break;
 791         case AMI_3000PLUS:
 792             strcat(model, "3000+");
 793             break;
 794         case AMI_4000:
 795             strcat(model, "4000");
 796             break;
 797         case AMI_4000T:
 798             strcat(model, "4000T");
 799             break;
 800         case AMI_CDTV:
 801             strcat(model, "CDTV");
 802             break;
 803         case AMI_CD32:
 804             strcat(model, "CD32");
 805             break;
 806         case AMI_DRACO:
 807             strcpy(model, "DRACO");
 808             break;
 809     }
 810 }
 811 
 812 
 813 int amiga_get_hardware_list(char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 814 {
 815     int len = 0;
 816 
 817     if (AMIGAHW_PRESENT(CHIP_RAM))
 818         len += sprintf(buffer+len, "Chip RAM:\t%ldK\n",
 819                        boot_info.bi_amiga.chip_size>>10);
 820     len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
 821                    boot_info.bi_amiga.psfreq, amiga_eclock);
 822     if (AMIGAHW_PRESENT(AMI_VIDEO)) {
 823         char *type;
 824         switch(boot_info.bi_amiga.chipset) {
 825             case CS_OCS:
 826                 type = "OCS";
 827                 break;
 828             case CS_ECS:
 829                 type = "ECS";
 830                 break;
 831             case CS_AGA:
 832                 type = "AGA";
 833                 break;
 834             default:
 835                 type = "Old or Unknown";
 836                 break;
 837         }
 838         len += sprintf(buffer+len, "Graphics:\t%s\n", type);
 839     }
 840 
 841 #define AMIGAHW_ANNOUNCE(name, str)                             \
 842     if (AMIGAHW_PRESENT(name))                          \
 843         len += sprintf (buffer+len, "\t%s\n", str)
 844 
 845     len += sprintf (buffer + len, "Detected hardware:\n");
 846 
 847     AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
 848     AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
 849     AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
 850     AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
 851     AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
 852     AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
 853     AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
 854     AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
 855     AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
 856     AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
 857     AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
 858     AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
 859     AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
 860     AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
 861     AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
 862     AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
 863     AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
 864     AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
 865     AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
 866     AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
 867     AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
 868     AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
 869     AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
 870     AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
 871     AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
 872     AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
 873     AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
 874     AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
 875     if (AMIGAHW_PRESENT(ZORRO))
 876         len += sprintf(buffer+len, "\tZorro AutoConfig: %d Expansion Device%s\n",
 877                        boot_info.bi_amiga.num_autocon,
 878                        boot_info.bi_amiga.num_autocon == 1 ? "" : "s");
 879 
 880     return(len);
 881 }

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