/* Tests for presence or absence of hardware registers.1* This code was originally in atari/config.c, but I noticed2* that it was also in drivers/nubus/nubus.c and I wanted to3* use it in hp300/config.c, so it seemed sensible to pull it4* out into its own file.5*6* The test is for use when trying to read a hardware register7* that isn't present would cause a bus error. We set up a8* temporary handler so that this doesn't kill the kernel.9*10* There is a test-by-reading and a test-by-writing; I present11* them here complete with the comments from the original atari12* config.c...13* -- PMM <[email protected]>, 05/199814*/1516/* This function tests for the presence of an address, specially a17* hardware register address. It is called very early in the kernel18* initialization process, when the VBR register isn't set up yet. On19* an Atari, it still points to address 0, which is unmapped. So a bus20* error would cause another bus error while fetching the exception21* vector, and the CPU would do nothing at all. So we needed to set up22* a temporary VBR and a vector table for the duration of the test.23*/2425#include <linux/module.h>2627int hwreg_present( volatile void *regp )28{29int ret = 0;30long save_sp, save_vbr;31long tmp_vectors[3];3233__asm__ __volatile__34( "movec %/vbr,%2\n\t"35"movel #Lberr1,%4@(8)\n\t"36"movec %4,%/vbr\n\t"37"movel %/sp,%1\n\t"38"moveq #0,%0\n\t"39"tstb %3@\n\t"40"nop\n\t"41"moveq #1,%0\n"42"Lberr1:\n\t"43"movel %1,%/sp\n\t"44"movec %2,%/vbr"45: "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)46: "a" (regp), "a" (tmp_vectors)47);4849return( ret );50}51EXPORT_SYMBOL(hwreg_present);5253/* Basically the same, but writes a value into a word register, protected54* by a bus error handler. Returns 1 if successful, 0 otherwise.55*/5657int hwreg_write( volatile void *regp, unsigned short val )58{59int ret;60long save_sp, save_vbr;61long tmp_vectors[3];6263__asm__ __volatile__64( "movec %/vbr,%2\n\t"65"movel #Lberr2,%4@(8)\n\t"66"movec %4,%/vbr\n\t"67"movel %/sp,%1\n\t"68"moveq #0,%0\n\t"69"movew %5,%3@\n\t"70"nop \n\t" /* If this nop isn't present, 'ret' may already be71* loaded with 1 at the time the bus error72* happens! */73"moveq #1,%0\n"74"Lberr2:\n\t"75"movel %1,%/sp\n\t"76"movec %2,%/vbr"77: "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)78: "a" (regp), "a" (tmp_vectors), "g" (val)79);8081return( ret );82}83EXPORT_SYMBOL(hwreg_write);84858687