summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /arch/m68k/mac
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r--arch/m68k/mac/config.c49
-rw-r--r--arch/m68k/mac/debug.c156
-rw-r--r--arch/m68k/mac/macboing.c357
-rw-r--r--arch/m68k/mac/macints.c203
-rw-r--r--arch/m68k/mac/mackeyb.c75
-rw-r--r--arch/m68k/mac/via6522.c23
6 files changed, 530 insertions, 333 deletions
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index f410182e0..8e902d0bd 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -55,9 +55,6 @@ extern char m68k_command_line[CL_SIZE];
void *mac_env; /* Loaded by the boot asm */
-/* The logical video addr. determined by head.S - testing */
-extern unsigned long mac_videobase;
-
/* The phys. video addr. - might be bogus on some machines */
unsigned long mac_orig_videoaddr;
@@ -65,7 +62,6 @@ unsigned long mac_orig_videoaddr;
extern int mac_keyb_init(void);
extern int mac_kbdrate(struct kbd_repeat *k);
extern void mac_kbd_leds(unsigned int leds);
-extern void mac_kbd_reset_setup(char*, int);
/* Mac specific irq functions */
extern void mac_init_IRQ (void);
@@ -100,17 +96,15 @@ extern void mac_debug_init(void);
extern void mac_debugging_long(int, long);
#ifdef CONFIG_MAGIC_SYSRQ
-
-/* XXX FIXME: Atari scancodes still */
static char mac_sysrq_xlate[128] =
- "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
- "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
- "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
- "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
- "\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */
- "\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
- "\000\000\000()/*789456123" /* 0x60 - 0x6f */
- "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
+ "\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */
+ "yt123465=97-80)o" /* 0x10 - 0x1f */
+ "u(ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
+ "\t `\000\033\000\000\000\000\000\000\000\000\000\000\000" /* 0x30 - 0x3f */
+ "\000.\000*\000+\000\000\000\000\000/\r\000-\000" /* 0x40 - 0x4f */
+ "\000\00001234567a89\000\000\000" /* 0x50 - 0x5f */
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
#endif
extern void (*kd_mksound)(unsigned int, unsigned int);
@@ -243,9 +237,7 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record))
mac_bi_data.id = *data;
break;
case BI_MAC_VADDR:
- /* save booter supplied videobase; use the one mapped in head.S! */
- mac_orig_videoaddr = *data;
- mac_bi_data.videoaddr = mac_videobase;
+ mac_bi_data.videoaddr = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
break;
case BI_MAC_VDEPTH:
mac_bi_data.videodepth = *data;
@@ -309,7 +301,6 @@ __initfunc(void config_mac(void))
mach_keyb_init = mac_keyb_init;
mach_kbdrate = mac_kbdrate;
mach_kbd_leds = mac_kbd_leds;
- kbd_reset_setup = mac_kbd_reset_setup;
mach_init_IRQ = mac_init_IRQ;
mach_request_irq = mac_request_irq;
mach_free_irq = mac_free_irq;
@@ -336,7 +327,7 @@ __initfunc(void config_mac(void))
#endif
kd_mksound = mac_mksound;
#ifdef CONFIG_MAGIC_SYSRQ
- mach_sysrq_key = 98; /* HELP */
+ mach_sysrq_key = 114; /* HELP */
mach_sysrq_shift_state = 8; /* Alt */
mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
mach_sysrq_xlate = mac_sysrq_xlate;
@@ -399,10 +390,10 @@ static struct mac_model mac_data_table[]=
*
*/
- { MAC_MODEL_II, "II", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS},
- { MAC_MODEL_IIX, "IIx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS},
- { MAC_MODEL_IICX, "IIcx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS},
- { MAC_MODEL_SE30, "SE/30", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS},
+ { MAC_MODEL_II, "II", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_IIX, "IIx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_IICX, "IIcx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_SE30, "SE/30", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
/*
* Weirdified MacII hardware - all subtley different. Gee thanks
@@ -425,7 +416,7 @@ static struct mac_model mac_data_table[]=
*/
{ MAC_MODEL_CLII, "Classic II", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_CCL, "Color Classic", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_CCL, "Color Classic", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
/*
* Some Mac LC machines. Basically the same as the IIci, ADB like IIsi
@@ -461,11 +452,11 @@ static struct mac_model mac_data_table[]=
* Performa - more LC type machines
*/
- { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
@@ -477,8 +468,8 @@ static struct mac_model mac_data_table[]=
* Centris - just guessing again; maybe like Quadra
*/
- { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
/*
@@ -551,7 +542,7 @@ void mac_identify(void)
m++;
}
if(m->ident==-1)
- mac_boom(5);
+ panic("mac model config data corrupt!\n");
}
/*
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 62a8a6187..5aa7ce6cf 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -36,7 +36,10 @@ extern unsigned long mac_videobase;
extern unsigned long mac_videodepth;
extern unsigned long mac_rowbytes;
-#define DEBUG_SCREEN
+extern void mac_serial_print(char *);
+
+#define DEBUG_HEADS
+#undef DEBUG_SCREEN
#define DEBUG_SERIAL
/*
@@ -129,121 +132,6 @@ void mac_debugging_long(int pos, long addr)
#endif
}
-/*
- * Penguin - used by head.S console; obsolete
- */
-char that_penguin[]={
-#include "that_penguin.h"
-};
-
-#ifdef DEBUG_SCREEN
-/*
- * B/W version of penguin, unfinished - any takers??
- */
-static char bw_penguin[]={
-#include "bw_penguin.h"
-};
-#endif
-
-void mac_debugging_penguin(int peng)
-{
-#ifdef DEBUG_SCREEN
- unsigned char *pengoffset;
- unsigned char *pptr;
- unsigned char *bwpdptr=bw_penguin;
- int i;
-#endif
-
-#ifdef DEBUG_SERIAL
- printk("Penguin: #%d !\n", peng);
-#endif
-
-#ifdef DEBUG_SCREEN
- if (!MACH_IS_MAC)
- return;
-
- if (mac_videodepth ==1)
- pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
- +5*peng;
- else
- pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
- +20*peng;
-
- pptr=pengoffset;
-
- for(i=0;i<36;i++)
- {
- memcpy(pptr,bwpdptr,4);
- bwpdptr+=4;
- pptr+=mac_rowbytes;
- }
-#endif
-}
-
-#ifdef DEBUG_SCREEN
-/*
- * B/W version of flaming Mac, unfinished (see above).
- */
-static char bw_kaboom_map[]={
-#include "bw_mac.h"
-};
-#endif
-
-#ifdef DEBUG_SCREEN
-static void mac_boom_boom(void)
-{
- static unsigned char *boomoffset=NULL;
- unsigned char *pptr;
- unsigned char *bwpdptr=bw_kaboom_map;
- int i;
-
-#ifdef DEBUG_SERIAL
- printk("BOOM !\n");
-#endif
-
- if (!MACH_IS_MAC)
- return;
-
- if(!boomoffset)
- if (mac_videodepth == 1) {
- boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes);
- } else {
- boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes);
- }
- else
- if (mac_videodepth == 1)
- boomoffset+=5;
- else
- boomoffset+=32;
-
- pptr=boomoffset;
-
- for(i=0;i<36;i++)
- {
- memcpy(pptr,bwpdptr,4);
- bwpdptr+=4;
- pptr+=mac_rowbytes;
- }
-}
-#endif
-
-void mac_boom(int booms)
-{
-#ifdef DEBUG_SCREEN
- int i;
-#endif
-
- if (!MACH_IS_MAC)
- return;
-
-#ifdef DEBUG_SCREEN
- for(i=0;i<booms;i++)
- mac_boom_boom();
- while(1);
-#endif
-}
-
-
#ifdef DEBUG_SERIAL
/*
* TODO: serial debug code
@@ -284,6 +172,29 @@ static struct console mac_console_driver = {
NULL
};
+/*
+ * Crude hack to get console output to the screen before the framebuffer
+ * is initialized (happens a lot later in 2.1!).
+ * We just use the console routines declared in head.S, this will interfere
+ * with regular framebuffer console output and should be used exclusively
+ * to debug kernel problems manifesting before framebuffer init (aka WSOD)
+ *
+ * To keep this hack from interfering with the regular console driver, either
+ * deregister this driver before/on framebuffer console init, or silence this
+ * function after the fbcon driver is running (will lose console messages!?).
+ * To debug real early bugs, need to write a 'mac_register_console_hack()'
+ * that is called from start_kernel() before setup_arch() and just registers
+ * this driver if Mac.
+ */
+
+void mac_debug_console_write (struct console *co, const char *str,
+ unsigned int count)
+{
+ mac_serial_print(str);
+}
+
+
+
/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
#define uSEC 1
@@ -486,19 +397,30 @@ __initfunc(void mac_debug_init(void))
/* Mac modem port */
mac_init_scc_port( B9600|CS8, 0 );
mac_console_driver.write = mac_scca_console_write;
+#ifdef CONFIG_SERIAL_CONSOLE
mac_console_driver.wait_key = mac_scca_console_wait_key;
+#endif
scc_port = 0;
}
else if (!strcmp( m68k_debug_device, "ser2" )) {
/* Mac printer port */
mac_init_scc_port( B9600|CS8, 1 );
mac_console_driver.write = mac_sccb_console_write;
+#ifdef CONFIG_SERIAL_CONSOLE
mac_console_driver.wait_key = mac_sccb_console_wait_key;
+#endif
scc_port = 1;
}
+#endif
+#ifdef DEBUG_HEADS
+ if ( !strcmp( m68k_debug_device, "scn" )
+ || !strcmp( m68k_debug_device, "con" )) {
+ /* display, using head.S console routines */
+ mac_console_driver.write = mac_debug_console_write;
+ }
+#endif
if (mac_console_driver.write)
register_console(&mac_console_driver);
-#endif
}
/*
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 95078a384..1731c929c 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -1,6 +1,12 @@
/*
* Mac bong noise generator. Note - we ought to put a boingy noise
* here 8)
+ *
+ * ----------------------------------------------------------------------
+ * 16.11.98:
+ * rewrote some functions, added support for Enhanced ASC (Quadras)
+ * after the NetBSD asc.c console bell patch by Colin Wood/Frederick Bruck
+ * Juergen Mellinger (juergen.mellinger@t-online.de)
*/
#include <linux/sched.h>
@@ -9,124 +15,281 @@
#include <asm/macintosh.h>
#include <asm/mac_asc.h>
+static int mac_asc_inited = 0;
+/*
+ * dumb triangular wave table
+ */
+static __u8 mac_asc_wave_tab[ 0x800 ];
+
+/*
+ * Alan's original sine table; needs interpolating to 0x800
+ * (hint: interpolate or hardwire [0 -> Pi/2[, it's symmetric)
+ */
static const signed char sine_data[] = {
0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
0, -39, -75, -103, -121, -127, -121, -103, -75, -39
};
-#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
-static void nosound( unsigned long ignored );
-static struct timer_list sound_timer = { NULL, NULL, 0, 0, nosound };
+/*
+ * where the ASC hides ...
+ */
+static volatile __u8* mac_asc_regs = ( void* )0x50F14000;
-static volatile unsigned char *asc_base=(void *)0x50F14000;
+/*
+ * sample rate; is this a good default value?
+ */
+static unsigned long mac_asc_samplespersec = 11050;
+static int mac_bell_duration = 0;
+static unsigned long mac_bell_phase; /* 0..2*Pi -> 0..0x800 (wavetable size) */
+static unsigned long mac_bell_phasepersample;
+
+/*
+ * some function protos
+ */
+static void mac_init_asc( void );
+static void mac_nosound( unsigned long );
+static void mac_quadra_start_bell( unsigned int, unsigned int, unsigned int );
+static void mac_quadra_ring_bell( unsigned long );
+static void mac_av_start_bell( unsigned int, unsigned int, unsigned int );
+static void ( *mac_special_bell )( unsigned int, unsigned int, unsigned int ) = NULL;
+/*
+ * our timer to start/continue/stop the bell
+ */
+static struct timer_list mac_sound_timer = { NULL, NULL, 0, 0, mac_nosound };
-void mac_mksound( unsigned int hz, unsigned int ticks )
+/*
+ * Sort of initialize the sound chip (called from mac_mksound on the first
+ * beep).
+ */
+static void mac_init_asc( void )
{
- static int inited = 0;
- unsigned long flags;
- int samples=512;
+ int i;
- if (macintosh_config->ident == MAC_MODEL_C660
- || macintosh_config->ident == MAC_MODEL_Q840)
+ /*
+ * do some machine specific initialization
+ * BTW:
+ * the NetBSD Quadra patch identifies the Enhanced Apple Sound Chip via
+ * mac_asc_regs[ 0x800 ] & 0xF0 != 0
+ * this makes no sense here, because we have to set the default sample
+ * rate anyway if we want correct frequencies
+ */
+ switch ( macintosh_config->ident )
{
- /*
- * The Quadra 660AV and 840AV use the "Singer" custom ASIC for sound I/O.
- * It appears to be similar to the "AWACS" custom ASIC in the Power Mac
- * [678]100. Because Singer and AWACS may have a similar hardware
- * interface, this would imply that the code in drivers/sound/dmasound.c
- * for AWACS could be used as a basis for Singer support. All we have to
- * do is figure out how to do DMA on the 660AV/840AV through the PSC and
- * figure out where the Singer hardware sits in memory. (I'd look in the
- * vicinity of the AWACS location in a Power Mac [678]100 first, or the
- * current location of the Apple Sound Chip--ASC--in other Macs.) The
- * Power Mac [678]100 info can be found in MkLinux Mach kernel sources.
- *
- * Quoted from Apple's Tech Info Library, article number 16405:
- * "Among desktop Macintosh computers, only the 660AV, 840AV, and Power
- * Macintosh models have 16-bit audio input and output capability
- * because of the AT&T DSP3210 hardware circuitry and the 16-bit Singer
- * codec circuitry in the AVs. The Audio Waveform Amplifier and
- * Converter (AWAC) chip in the Power Macintosh performs the same
- * 16-bit I/O functionality. The PowerBook 500 series computers
- * support 16-bit stereo output, but only mono input."
- *
- * http://til.info.apple.com/techinfo.nsf/artnum/n16405
- *
- * --David Kilzer
- */
+ case MAC_MODEL_IIFX:
+ /*
+ * The IIfx is always special ...
+ */
+ mac_asc_regs = ( void* )0x50010000;
+ break;
+ /*
+ * not sure about how correct this list is
+ * machines with the EASC enhanced apple sound chip
+ */
+ case MAC_MODEL_Q630:
+ case MAC_MODEL_P475:
+ mac_special_bell = mac_quadra_start_bell;
+ mac_asc_samplespersec = 22150;
+ break;
+ case MAC_MODEL_Q650:
+ case MAC_MODEL_Q700:
+ case MAC_MODEL_Q800:
+ case MAC_MODEL_Q900:
+ case MAC_MODEL_Q950:
+ /*
+ * Currently not implemented!
+ */
+ /*
+ * The Quadra 660AV and 840AV use the "Singer" custom ASIC for sound I/O.
+ * It appears to be similar to the "AWACS" custom ASIC in the Power Mac
+ * [678]100. Because Singer and AWACS may have a similar hardware
+ * interface, this would imply that the code in drivers/sound/dmasound.c
+ * for AWACS could be used as a basis for Singer support. All we have to
+ * do is figure out how to do DMA on the 660AV/840AV through the PSC and
+ * figure out where the Singer hardware sits in memory. (I'd look in the
+ * vicinity of the AWACS location in a Power Mac [678]100 first, or the
+ * current location of the Apple Sound Chip--ASC--in other Macs.) The
+ * Power Mac [678]100 info can be found in MkLinux Mach kernel sources.
+ *
+ * Quoted from Apple's Tech Info Library, article number 16405:
+ * "Among desktop Macintosh computers, only the 660AV, 840AV, and Power
+ * Macintosh models have 16-bit audio input and output capability
+ * because of the AT&T DSP3210 hardware circuitry and the 16-bit Singer
+ * codec circuitry in the AVs. The Audio Waveform Amplifier and
+ * Converter (AWAC) chip in the Power Macintosh performs the same
+ * 16-bit I/O functionality. The PowerBook 500 series computers
+ * support 16-bit stereo output, but only mono input."
+ *
+ * http://til.info.apple.com/techinfo.nsf/artnum/n16405
+ *
+ * --David Kilzer
+ */
+ mac_special_bell = mac_av_start_bell;
+ break;
+ }
+
+ /*
+ * init the wave table with a simple triangular wave
+ * A sine wave would sure be nicer here ...
+ */
+ for ( i = 0; i < 0x400; i++ )
+ {
+ mac_asc_wave_tab[ i ] = i / 4;
+ mac_asc_wave_tab[ i + 0x400 ] = 0xFF - i / 4;
+ }
+ mac_asc_inited = 1;
+}
+/*
+ * Called to make noise; current single entry to the boing driver.
+ * Does the job for simple ASC, calls other routines else.
+ * XXX Fixme:
+ * Should be split into asc_mksound, easc_mksound, av_mksound and
+ * function pointer set in mac_init_asc which would be called at
+ * init time.
+ * _This_ is rather ugly ...
+ */
+void mac_mksound( unsigned int freq, unsigned int length )
+{
+ __u32 cfreq = ( freq << 5 ) / 468;
+ __u32 flags;
+ int i;
+
+ if ( !mac_asc_inited )
+ mac_init_asc();
+
+ if ( mac_special_bell )
+ {
+ mac_special_bell( freq, length, 128 );
return;
}
-
- if(!inited)
+
+ if ( freq < 20 || freq > 20000 || length == 0 )
{
- int i=0;
- int j=0;
- int k=0;
- int l=0;
-
- /*
- * The IIfx strikes again!
- */
-
- if(macintosh_config->ident==MAC_MODEL_IIFX)
- asc_base=(void *)0x50010000;
-
- for(i=0;i<samples;i++)
- {
- asc_base[i]=sine_data[j];
- asc_base[i+512]=sine_data[j];
- asc_base[i+1024]=sine_data[j];
- asc_base[i+1536]=sine_data[j];
- j++;
- if(j==DATA_SIZE)
- j=0;
- if(i&1)
- k++;
- if(k==DATA_SIZE)
- k=0;
- if((i&3)==3)
- l++;
- if(l==DATA_SIZE)
- l=0;
- }
- inited=1;
+ mac_nosound( 0 );
+ return;
}
- save_flags(flags);
+
+ save_flags( flags );
cli();
- del_timer( &sound_timer );
- if (hz > 20 && hz < 32767) {
- int i;
- u_long asc_pulses=((hz<<5)*samples)/468;
- for(i=0;i<4;i++)
+ del_timer( &mac_sound_timer );
+
+ for ( i = 0; i < 0x800; i++ )
+ mac_asc_regs[ i ] = 0;
+ for ( i = 0; i < 0x800; i++ )
+ mac_asc_regs[ i ] = mac_asc_wave_tab[ i ];
+
+ for ( i = 0; i < 8; i++ )
+ *( __u32* )( ( __u32 )mac_asc_regs + ASC_CONTROL + 0x814 + 8 * i ) = cfreq;
+
+ mac_asc_regs[ 0x807 ] = 0;
+ mac_asc_regs[ ASC_VOLUME ] = 128;
+ mac_asc_regs[ 0x805 ] = 0;
+ mac_asc_regs[ 0x80F ] = 0;
+ mac_asc_regs[ ASC_MODE ] = ASC_MODE_SAMPLE;
+ mac_asc_regs[ ASC_ENABLE ] = ASC_ENABLE_SAMPLE;
+
+ mac_sound_timer.expires = jiffies + length;
+ add_timer( &mac_sound_timer );
+
+ restore_flags( flags );
+}
+
+/*
+ * regular ASC: stop whining ..
+ */
+static void mac_nosound( unsigned long ignored )
+{
+ mac_asc_regs[ ASC_ENABLE ] = 0;
+}
+
+/*
+ * EASC entry; init EASC, don't load wavetable, schedule 'start whining'.
+ */
+static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
+{
+ __u32 flags;
+
+ /* if the bell is already ringing, ring longer */
+ if ( mac_bell_duration > 0 )
+ {
+ mac_bell_duration += length;
+ return;
+ }
+
+ mac_bell_duration = length;
+ mac_bell_phase = 0;
+ mac_bell_phasepersample = ( freq * sizeof( mac_asc_wave_tab ) ) / mac_asc_samplespersec;
+ /* this is reasonably big for small frequencies */
+
+ save_flags( flags );
+ cli();
+
+ /* set the volume */
+ mac_asc_regs[ 0x806 ] = volume;
+
+ /* set up the ASC registers */
+ if ( mac_asc_regs[ 0x801 ] != 1 )
+ {
+ /* select mono mode */
+ mac_asc_regs[ 0x807 ] = 0;
+ /* select sampled sound mode */
+ mac_asc_regs[ 0x802 ] = 0;
+ /* ??? */
+ mac_asc_regs[ 0x801 ] = 1;
+ mac_asc_regs[ 0x803 ] |= 0x80;
+ mac_asc_regs[ 0x803 ] &= 0x7F;
+ }
+
+ mac_sound_timer.function = mac_quadra_ring_bell;
+ mac_sound_timer.expires = jiffies + 1;
+ add_timer( &mac_sound_timer );
+
+ restore_flags( flags );
+}
+
+/*
+ * EASC 'start/continue whining'; I'm not sure why the above function didn't
+ * already load the wave table, or at least call this one...
+ * This piece keeps reloading the wave table until done.
+ */
+static void mac_quadra_ring_bell( unsigned long ignored )
+{
+ int i, count = mac_asc_samplespersec / HZ;
+ __u32 flags;
+
+ /*
+ * we neither want a sound buffer overflow nor underflow, so we need to match
+ * the number of samples per timer interrupt as exactly as possible.
+ * using the asc interrupt will give better results in the future
+ * ...and the possibility to use a real sample (a boingy noise, maybe...)
+ */
+
+ save_flags( flags );
+ cli();
+
+ del_timer( &mac_sound_timer );
+
+ if ( mac_bell_duration-- > 0 )
+ {
+ for ( i = 0; i < count; i++ )
{
- asc_base[ASC_FREQ(i,0)]=0x00;
- asc_base[ASC_FREQ(i,1)]=20;
- asc_base[ASC_FREQ(i,2)]=0x00;
- asc_base[ASC_FREQ(i,3)]=20;
- asc_base[ASC_FREQ(i,4)]=(asc_pulses>>24)&0xFF;
- asc_base[ASC_FREQ(i,5)]=(asc_pulses>>16)&0xFF;
- asc_base[ASC_FREQ(i,6)]=(asc_pulses>>8)&0xFF;
- asc_base[ASC_FREQ(i,7)]=(asc_pulses>>0)&0xFF;
+ mac_bell_phase += mac_bell_phasepersample;
+ mac_asc_regs[ 0 ] = mac_asc_wave_tab[ mac_bell_phase & ( sizeof( mac_asc_wave_tab ) - 1 ) ];
}
- asc_base[ASC_CHAN]=0x03;
- asc_base[ASC_VOLUME]=128;
- asc_base[ASC_MODE]=ASC_MODE_SAMPLE;
- asc_base[ASC_ENABLE]=ASC_ENABLE_SAMPLE;
- if (ticks) {
- sound_timer.expires = jiffies + ticks;
- add_timer( &sound_timer );
- }
- } else {
- nosound( 0 );
+ mac_sound_timer.expires = jiffies + 1;
+ add_timer( &mac_sound_timer );
}
- restore_flags(flags);
+ else
+ mac_asc_regs[ 0x801 ] = 0;
+
+ restore_flags( flags );
}
-
-static void nosound( unsigned long ignored )
+/*
+ * AV code - please fill in.
+ */
+static void mac_av_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
{
- asc_base[ASC_ENABLE]=0;
-}
+}
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index b703cb275..87e6692d4 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -163,7 +163,14 @@ static unsigned long nubus_irqs[8];
static unsigned long *mac_irqs[8];
/*
- * VIA2 / RBV register base pointers
+ * Some special nutcases ...
+ */
+
+static unsigned long mac_ide_irqs = 0;
+static unsigned long nubus_stuck_events = 0;
+
+/*
+ * VIA/RBV/OSS/PSC register base pointers
*/
volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS;
@@ -217,9 +224,13 @@ void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs);
static void via_do_nubus(int slot, void *via, struct pt_regs *regs);
/* #define DEBUG_MACINTS */
-/* #define DEBUG_NUBUS_INT */
+
+#define DEBUG_SPURIOUS
+#define DEBUG_NUBUS_SPURIOUS
+#define DEBUG_NUBUS_INT
+
/* #define DEBUG_VIA */
-/* #define DEBUG_VIA_NUBUS */
+#define DEBUG_VIA_NUBUS
void mac_init_IRQ(void)
{
@@ -247,7 +258,7 @@ void mac_init_IRQ(void)
/* yes, this is messy - the IIfx deserves a class of his own */
if (macintosh_config->ident == MAC_MODEL_IIFX) {
- /* no real VIA2, the OSS seems _very_different */
+ /* no real VIA2, the OSS seems _very_ different */
via2_is_oss = 1;
/* IIfx has OSS, at a different base address than RBV */
rbv_regp = (unsigned char *) OSS_BAS;
@@ -351,6 +362,12 @@ void mac_init_IRQ(void)
mac_irqs[7] = &nubus_irqs[0];
/*
+ * Nubus Macs: turn off the Nubus dispatch interrupt for now
+ */
+
+ mac_turnoff_irq(IRQ_MAC_NUBUS);
+
+ /*
* AV Macs: shutup the PSC ints
*/
if (macintosh_config->ident == MAC_MODEL_C660
@@ -430,8 +447,10 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
return 0;
}
- /* add similar hack for Nubus pseudo-irq here - hide nubus_request_irq */
-
+ /*
+ * code below: only for VIA irqs currently
+ * add similar hack for Nubus pseudo-irq here - hide nubus_request_irq
+ */
via = (volatile unsigned char *) via_table[srcidx];
if (!via)
return -EINVAL;
@@ -459,7 +478,7 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
if (irq == IRQ_IDX(IRQ_MAC_SCSI)) {
/*
* Set vPCR for SCSI interrupts. (what about RBV here?)
- * 980429 MS: RBV is ok, OSS seems to be differentt
+ * 980429 MS: RBV is ok, OSS seems to be different
*/
if (!via2_is_oss)
if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
@@ -602,7 +621,10 @@ void mac_disable_irq (unsigned int irq)
/*
* In opposite to {en,dis}able_irq, requests between turn{off,on}_irq are not
- * "stored". This is done with the VIA interrupt enable register
+ * "stored". This is done with the VIA interrupt enable register on VIAs.
+ *
+ * Note: Using these functions on non-VIA/OSS/PSC ints will panic, or at least
+ * have undesired side effects.
*/
void mac_turnon_irq( unsigned int irq )
@@ -615,14 +637,14 @@ void mac_turnon_irq( unsigned int irq )
if (!via)
return;
- if (srcidx == SRC_VIA2 && via2_is_rbv)
+ if (srcidx == SRC_VIA2 && via2_is_rbv) /* RBV as VIA2 */
via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx)));
- else if (srcidx == SRC_VIA2 && via2_is_oss)
+ else if (srcidx == SRC_VIA2 && via2_is_oss) /* OSS */
via_write(oss_regp, oss_map[irqidx]+8, 2);
- else if (srcidx > SRC_VIA2)
+ else if (srcidx > SRC_VIA2) /* hope AVs have VIA2 */
via_write(via, (0x104 + 0x10*srcidx),
via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx)));
- else
+ else /* VIA1+2 */
via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx)));
}
@@ -637,9 +659,9 @@ void mac_turnoff_irq( unsigned int irq )
if (!via)
return;
- if (srcidx == SRC_VIA2 && via2_is_rbv)
+ if (srcidx == SRC_VIA2 && via2_is_rbv) /* RBV as VIA2 */
via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx)));
- else if (srcidx == SRC_VIA2 && via2_is_oss)
+ else if (srcidx == SRC_VIA2 && via2_is_oss) /* OSS */
via_write(oss_regp, oss_map[irqidx]+8, 0);
/*
* VIA2 is fixed. The stuff above VIA2 is for later
@@ -648,7 +670,7 @@ void mac_turnoff_irq( unsigned int irq )
else if (srcidx > SRC_VIA2)
via_write(via, (0x104 + 0x10*srcidx),
via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx)));
- else
+ else /* VIA1+2 */
via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx)));
}
@@ -694,12 +716,18 @@ int mac_irq_pending( unsigned int irq )
return (pending);
}
+/*
+ * for /proc/interrupts: log interrupt stats broken down by
+ * autovector int first, then by actual interrupt source.
+ */
+
int mac_get_irq_list (char *buf)
{
int i, len = 0;
int srcidx, irqidx;
for (i = VIA1_SOURCE_BASE; i < NUM_MAC_SOURCES+8; ++i) {
+ /* XXX fixme: IRQ_SRC_MASK should cover VIA1 - Nubus */
srcidx = ((i & IRQ_SRC_MASK)>>3) - 1;
irqidx = (i & IRQ_IDX_MASK);
@@ -764,6 +792,32 @@ int mac_get_irq_list (char *buf)
}
if (num_spurious)
len += sprintf(buf+len, "spurio.: %10u\n", num_spurious);
+
+ /*
+ * XXX Fixme: Nubus sources are never logged above ...
+ */
+
+ len += sprintf(buf+len, "Nubus interrupts:\n");
+
+ for (i = 0; i < 7; i++) {
+ if (nubus_handler[i].handler == nubus_wtf)
+ continue;
+ len += sprintf(buf+len, "nubus %01X: %10lu ",
+ i+9,
+ nubus_irqs[i]);
+ len += sprintf(buf+len, "%s\n",
+ nubus_param[i].devname);
+
+ }
+ len += sprintf(buf+len, "nubus spurious ints: %10lu\n",
+ nubus_irqs[7]);
+ len += sprintf(buf+len, "nubus stuck events : %10lu\n",
+ nubus_stuck_events);
+#ifdef CONFIG_BLK_DEV_IDE
+ len += sprintf(buf+len, "nubus/IDE interrupt: %10lu\n",
+ mac_ide_irqs);
+#endif
+
return len;
}
@@ -784,8 +838,9 @@ void via_scsi_clear(void)
void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef DEBUG_VIA
- printk("Unexpected IRQ %d\n", irq);
+#ifdef DEBUG_SPURIOUS
+ if (console_loglevel > 6)
+ printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
#endif
}
@@ -861,6 +916,18 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
}
/*
+ * Unexpected via interrupt
+ */
+
+void via_wtf(int slot, void *via, struct pt_regs *regs)
+{
+#ifdef DEBUG_SPURIOUS
+ if (console_loglevel > 6)
+ printk("Unexpected nubus event %d on via %p\n",slot,via);
+#endif
+}
+
+/*
* The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
* via6522.c :-), disable/pending masks added.
* The int *viaidx etc. is just to keep the prototype happy ...
@@ -1115,17 +1182,6 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs)
}
/*
- * Unexpected via interrupt
- */
-
-void via_wtf(int slot, void *via, struct pt_regs *regs)
-{
-#ifdef DEBUG_VIA
- printk("Unexpected event %d on via %p\n",slot,via);
-#endif
-}
-
-/*
* Nubus / SCSI interrupts; OSS style
* The OSS is even more different than the RBV. OSS appears to stand for
* Obscenely Screwed Silicon ...
@@ -1264,8 +1320,9 @@ void oss_irq(int irq, void *dev_id, struct pt_regs *regs)
void nubus_wtf(int slot, void *via, struct pt_regs *regs)
{
-#ifdef DEBUG_VIA_NUBUS
- printk("Unexpected interrupt on nubus slot %d\n",slot);
+#ifdef DEBUG_NUBUS_SPURIOUS
+ if (console_loglevel > 6)
+ printk("Unexpected interrupt on nubus slot %d\n",slot);
#endif
}
@@ -1279,9 +1336,10 @@ void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs)
int i;
/* 1+2: compatibility with PSC ! */
for (i = 1; i < 3; i++) /* currently only these two used */
- if (scc_handler[i].handler != mac_default_handler)
+ if (scc_handler[i].handler != mac_default_handler) {
(scc_handler[i].handler)(i, scc_handler[i].dev_id, regs);
-
+ scc_irqs[i]++;
+ }
}
/*
@@ -1310,7 +1368,7 @@ void psc_irq(int irq, void *dev_id, struct pt_regs *regs)
if(events==0)
{
#ifdef DEBUG_VIA
- printk("rbv_irq: nothing pending, flags %x mask %x!\n",
+ printk("psc_irq: nothing pending, flags %x mask %x!\n",
via_read(via, pIFR), via_read(via,pIER));
#endif
mac_irqs[srcidx][7]++;
@@ -1319,7 +1377,7 @@ void psc_irq(int irq, void *dev_id, struct pt_regs *regs)
#ifdef DEBUG_VIA
/*
- * limited verbosity for RBV interrupts (add more if needed)
+ * limited verbosity for PSC interrupts (add more if needed)
*/
if ( srcidx == 1 && events != 1<<3 && events != 1<<1 ) /* SCSI IRQ */
printk("psc_irq: irq %d srcidx+1 %d events %x !\n", irq, srcidx+1, events);
@@ -1423,6 +1481,7 @@ int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct
if (!nubus_active && !via2_is_oss) {
request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK,
"nubus dispatch", via_do_nubus);
+ mac_turnon_irq(IRQ_MAC_NUBUS);
}
nubus_active|=1<<slot;
@@ -1472,6 +1531,7 @@ int nubus_free_irq(int slot)
* IDE interrupt hook
*/
extern void (*mac_ide_intr_hook)(int, void *, struct pt_regs *);
+extern int (*mac_ide_irq_p_hook)(void);
#endif
/*
@@ -1479,13 +1539,13 @@ extern void (*mac_ide_intr_hook)(int, void *, struct pt_regs *);
*/
static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
{
- unsigned char map;
+ unsigned char map, allints;
int i;
int ct=0;
-
-/* printk("nubus interrupt\n");*/
+ int ide_pending = 0;
/* lock the nubus interrupt */
+ /* That's just 'clear Nubus IRQ bit in VIA2' BTW. Pretty obsolete ? */
if (via2_is_rbv)
via_write(rbv_regp, rIFR, 0x82);
else
@@ -1493,36 +1553,69 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
#ifdef CONFIG_BLK_DEV_MAC_IDE
/* IDE hack */
- if (mac_ide_intr_hook)
+ if (mac_ide_intr_hook) {
/* 'slot' is lacking the machspec bit in 2.0 */
/* need to pass proper dev_id = hwgroup here */
mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs);
+ mac_ide_irqs++;
+ }
#endif
while(1)
{
if (via2_is_rbv)
- map = ~via_read(rbv_regp, rBufA);
+ allints = ~via_read(rbv_regp, rBufA);
else
- map = ~via_read(via2_regp, vBufA);
+ allints = ~via_read(via2_regp, vBufA);
- if( (map = (map&nubus_active)) ==0 ) {
-#ifdef DEBUG_NUBUS_INT
- printk("nubus_irq: nothing pending, map %x mask %x\n",
- map, nubus_active);
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ if (mac_ide_irq_p_hook)
+ ide_pending = mac_ide_irq_p_hook();
+#endif
+
+ if ( (map = (allints&nubus_active)) == 0
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ && !ide_pending
#endif
- nubus_irqs[7]++;
+ )
+ {
+ if (ct == 0) {
+#ifdef DEBUG_VIA_NUBUS
+ if (console_loglevel > 5)
+ printk("nubus_irq: nothing pending, map %x mask %x active %x\n",
+ allints, nubus_active, map);
+#endif
+ nubus_irqs[7]++;
+ }
+ /* clear it */
+ if (allints)
+ if (via2_is_rbv)
+ via_write(rbv_regp, rIFR, 0x02);
+ else
+ via_write(via2_regp, vIFR, 0x02);
break;
}
-#ifdef DEBUG_NUBUS_INT
- printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+
+#ifdef DEBUG_VIA_NUBUS
+ if (console_loglevel > 6)
+ printk("nubus_irq: map %x mask %x active %x\n",
+ allints, nubus_active, map);
+#endif
+
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ if (mac_ide_intr_hook && ide_pending) {
+ mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs);
+ mac_ide_irqs++;
+ }
#endif
if(ct++>2)
{
-#ifdef DEBUG_NUBUS_INT
- printk("nubus stuck events - %d/%d\n", map, nubus_active);
-#endif
+ if (console_loglevel > 5)
+ printk("nubus stuck events - %x/%x/%x ide %x\n",
+ allints, nubus_active, map, ide_pending);
+ nubus_stuck_events++;
+
return;
}
@@ -1579,12 +1672,14 @@ static void oss_do_nubus(int slot, void *via, struct pt_regs *regs)
printk("nubus_irq: map %x mask %x\n", map, nubus_active);
#endif
if( (map = (map&nubus_active)) ==0 ) {
+ if (ct == 0) {
#ifdef CONFIG_BLK_DEV_MAC_IDE
- if (!mac_ide_intr_hook)
- printk("nubus_irq: nothing pending, map %x mask %x\n",
- map, nubus_active);
+ if (!mac_ide_intr_hook)
+ printk("nubus_irq: nothing pending, map %x mask %x\n",
+ map, nubus_active);
#endif
- nubus_irqs[7]++;
+ nubus_irqs[7]++;
+ }
break;
}
diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c
index 64cd5e1f8..5a6ae7c75 100644
--- a/arch/m68k/mac/mackeyb.c
+++ b/arch/m68k/mac/mackeyb.c
@@ -1,5 +1,12 @@
/*
- * linux/arch/m68k/mac/mackeyb.c
+ * linux/arch/m68k/mac/mackeyb.c
+ *
+ * Keyboard driver for Macintosh computers.
+ *
+ * Adapted from drivers/macintosh/key_mac.c and arch/m68k/atari/akakeyb.c
+ * (see that file for its authors and contributors).
+ *
+ * Copyright (C) 1997 Michael Schmitz.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
@@ -10,6 +17,7 @@
* misc. keyboard stuff (everything not in adb-bus.c or keyb_m68k.c)
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/kd.h>
@@ -59,8 +67,15 @@ extern void put_queue(int);
static void mac_leds_done(struct adb_request *);
static void keyboard_input(unsigned char *, int, struct pt_regs *);
static void mouse_input(unsigned char *, int, struct pt_regs *);
-/* Hook for mouse driver */
-void (*adb_mouse_interrupt_hook) (char *, int);
+
+#ifdef CONFIG_ADBMOUSE
+/* XXX: Hook for mouse driver */
+void (*adb_mouse_interrupt_hook)(unsigned char *, int);
+int adb_emulate_buttons = 0;
+int adb_button2_keycode = 0x7d; /* right control key */
+int adb_button3_keycode = 0x7c; /* right option key */
+#endif
+
/* The mouse driver - for debugging */
extern void adb_mouse_interrupt(char *, int);
/* end keyb */
@@ -275,9 +290,11 @@ input_keycode(int keycode, int repeat)
kbd = kbd_table + fg_console;
up_flag = (keycode & 0x80);
keycode &= 0x7f;
+
if (!repeat)
del_timer(&repeat_timer);
+#ifdef CONFIG_ADBMOUSE
/*
* XXX: Add mouse button 2+3 fake codes here if mouse open.
* As we only report up/down events, keep track of faked buttons.
@@ -289,7 +306,8 @@ input_keycode(int keycode, int repeat)
* (wanted: command and alt/option, or KP= and KP( ...)
* Debug version; might be rewritten to be faster on normal keys.
*/
- if (adb_mouse_interrupt_hook || console_loglevel >= 8) {
+ if (adb_emulate_buttons
+ && (adb_mouse_interrupt_hook || console_loglevel >= 8)) {
unsigned char button, button2, button3, fake_event;
static unsigned char button2state=0, button3state=0; /* up */
/* faked ADB packet */
@@ -297,21 +315,20 @@ input_keycode(int keycode, int repeat)
button = 0;
fake_event = 0;
- switch (keycode) { /* which 'button' ? */
- case 0x7c: /* R-option */
- button2 = (!up_flag); /* new state */
- if (button2 != button2state) /* change ? */
- button = 2;
- button2state = button2; /* save state */
- fake_event = 2;
- break;
- case 0x7d: /* R-control */
- button3 = (!up_flag); /* new state */
- if (button3 != button3state) /* change ? */
- button = 3;
- button3state = button3; /* save state */
- fake_event = 3;
- break;
+ if (keycode == adb_button2_keycode) { /* which 'button' ? */
+ /* R-option */
+ button2 = (!up_flag); /* new state */
+ if (button2 != button2state) /* change ? */
+ button = 2;
+ button2state = button2; /* save state */
+ fake_event = 2;
+ } else if (keycode == adb_button3_keycode) {
+ /* R-control */
+ button3 = (!up_flag); /* new state */
+ if (button3 != button3state) /* change ? */
+ button = 3;
+ button3state = button3; /* save state */
+ fake_event = 3;
}
#ifdef DEBUG_ADBMOUSE
if (fake_event && console_loglevel >= 8)
@@ -340,6 +357,7 @@ input_keycode(int keycode, int repeat)
if (fake_event)
return;
}
+#endif /* CONFIG_ADBMOUSE */
/*
* Convert R-shift/control/option to L version.
@@ -365,16 +383,18 @@ input_keycode(int keycode, int repeat)
* transition into a key-down transition.
* MSch: need to turn each caps-lock event into a down-up
* double event (keyboard code assumes caps-lock is a toggle)
+ * 981127: fix LED behavior (kudos atong!)
*/
-#if 0
- if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
- up_flag = 0;
-#else
- if (keycode == 0x39) {
+ switch (keycode) {
+ case 0x39:
handle_scancode(keycode); /* down */
up_flag = 0x80; /* see below ... */
+ mark_bh(KEYBOARD_BH);
+ break;
+ case 0x47:
+ mark_bh(KEYBOARD_BH);
+ break;
}
-#endif
}
handle_scancode(keycode + up_flag);
@@ -740,8 +760,3 @@ __initfunc(int mac_keyb_init(void))
return 0;
}
-
-/* for "kbd-reset" cmdline param */
-__initfunc(void mac_kbd_reset_setup(char *str, int *ints))
-{
-}
diff --git a/arch/m68k/mac/via6522.c b/arch/m68k/mac/via6522.c
index 08ca49071..05e6f44e4 100644
--- a/arch/m68k/mac/via6522.c
+++ b/arch/m68k/mac/via6522.c
@@ -304,10 +304,11 @@ void mac_reset(void)
unsigned long flags;
unsigned long *reset_hook;
- save_flags(flags);
- cli();
-
/* need ROMBASE in booter */
+ /* indeed, plus need to MAP THE ROM !! */
+
+ if (mac_bi_data.rombase == 0)
+ mac_bi_data.rombase = 0x40800000;
/* works on some */
rom_reset = (void *) (mac_bi_data.rombase + 0xa);
@@ -318,12 +319,22 @@ void mac_reset(void)
printk("ROM reset hook: %p\n", *reset_hook);
rom_reset = *reset_hook;
#endif
+ if (macintosh_config->ident == MAC_MODEL_SE30) {
+ /*
+ * MSch: Machines known to crash on ROM reset ...
+ */
+ printk("System halted.\n");
+ while(1);
+ } else {
+ save_flags(flags);
+ cli();
- rom_reset();
+ rom_reset();
- restore_flags(flags);
+ restore_flags(flags);
+ }
- /* We never make it this far... */
+ /* We never make it this far... it usually panics above. */
printk ("Restart failed. Please restart manually.\n");
/* XXX - delay do we need to spin here ? */