/*
 *  linux/include/linux/atariconf.h
 *
 *  Copyright (C) 1994        Bj”rn Brauel
 *
 *  5/2/94 Roman Hodek:
 *    Added setup of mach_add_isr to atari_add_isr and runtime determination
 *    of hardware model (TT/Falcon)
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file README.legal in the main directory of this archive
 * for more details.
 */

#ifndef _LINUX_ATARICONF_H_
#define _LINUX_ATARICONF_H_ 1

#include <linux/atarihw.h>
#include <linux/bootinfo.h>

extern void atari_sched_init(isrfunc);
extern unsigned long atari_keyb_init(unsigned long);
extern void atari_init_INTS (void);
extern int atari_add_isr (unsigned long, isrfunc, int, void *);
extern unsigned long atari_gettimeoffset (void);
extern void atari_gettod (struct mktime *);
extern void atari_check_partition (struct gendisk *hd, unsigned int dev);
extern void atari_mksound( unsigned int count, unsigned int ticks );
extern void atari_reset( void );
extern struct consw ata_con;


/* This function tests for the presence of an address, specially a
 * hardware register address. It is called very early in the kernel
 * initialization process, when the VBR register isn't set up yet. On
 * an Atari, it still points to address 0, which is unmapped. So a bus
 * error would cause another bus error while fetching the exception
 * vector, and the CPU would do nothing at all. So we needed to set up
 * a temporary VBR and a vector table for the duration of the test.
 */

static __inline__ int hwreg_present( volatile void *regp )

{	int		ret;
	long	save_sp, save_vbr;
	static long tmp_vectors[3] = { 0, 0, (long)&&after_test };
	
	__asm__ __volatile__
	(	"movec	vbr,%2\n\t"					   /* save vbr value            */
	    "movec	%4,vbr\n\t"					   /* set up temporary vectors  */
		"movel	sp,%1\n\t"		               /* save sp                   */
		"moveq	#0,%0\n\t"		               /* assume not present        */
		"tstb	%3@\n\t"		               /* access given hardware reg */
		"moveq	#1,%0"			               /* comes here only if reg    */
											   /* is present                */
		: "=d" (ret), "=r" (save_sp), "=r" (save_vbr)
		: "a" (regp), "r" (tmp_vectors)
	);
  after_test:
	__asm__ __volatile__
	(	"movel	%0,sp\n\t"					   /* restore sp                */
		"movec	%1,vbr"						   /* restore vbr               */
		: : "r" (save_sp), "r" (save_vbr) : "sp"
	);

	return( ret );
}

static __inline__ void config_atari(void)
{
    mach_sched_init      = atari_sched_init;
    mach_keyb_init       = atari_keyb_init;
    mach_init_INTS       = atari_init_INTS;
	mach_add_isr         = atari_add_isr;
    mach_gettimeoffset   = atari_gettimeoffset;
    mach_gettod          = atari_gettod;
    mach_check_partition = atari_check_partition;
	mach_mksound         = atari_mksound;
	mach_reset           = atari_reset;
    conswitchp	         = &ata_con;

	/* ++roman:
	 * Determine hardware model: TT or Falcon (for now, others may be added)
	 * This is done by probing access to certain hardware registers unique to
	 * the machine type.
	 */

	printk( "Atari model is " );
	if (hwreg_present( &tt_mfp.par_dt_reg )) {
		boot_info.bi_atari.model = ATARI_TT;
		printk( "a TT\n" );
	}
	else if (hwreg_present( f030_xreg )) {
		boot_info.bi_atari.model = ATARI_FALCON;
		printk( "a FALCON\n" );
	}
	else {
		printk( "unknown!\n" );
		panic( "Cannot determine Atari model.\n" );
	}
}

#endif /* linux/atariconf.h */
