summaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
commit482368b1a8e45430672c58c9a42e7d2004367126 (patch)
treece2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /arch/m68k
parente4d0251c6f56ab2e191afb70f80f382793e23f74 (diff)
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/atari/joystick.c6
-rw-r--r--arch/m68k/atari/stram.c2
-rw-r--r--arch/m68k/config.in38
-rw-r--r--arch/m68k/kernel/Makefile2
-rw-r--r--arch/m68k/kernel/entry.S6
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c1
-rw-r--r--arch/m68k/mac/Makefile2
-rw-r--r--arch/m68k/mac/adb-bus.c2699
-rw-r--r--arch/m68k/mac/baboon.c124
-rw-r--r--arch/m68k/mac/config.c415
-rw-r--r--arch/m68k/mac/iop.c2
-rw-r--r--arch/m68k/mac/macints.c304
-rw-r--r--arch/m68k/mac/mackeyb.c762
-rw-r--r--arch/m68k/mac/misc.c689
-rw-r--r--arch/m68k/mac/oss.c38
-rw-r--r--arch/m68k/mac/psc.c16
-rw-r--r--arch/m68k/mac/via.c258
-rw-r--r--arch/m68k/mm/motorola.c2
-rw-r--r--arch/m68k/mm/sun3mmu.c2
19 files changed, 1204 insertions, 4164 deletions
diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
index bf82e67ea..86bd24c73 100644
--- a/arch/m68k/atari/joystick.c
+++ b/arch/m68k/atari/joystick.c
@@ -12,6 +12,7 @@
#include <linux/major.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
#include <asm/atarikb.h>
#include <asm/atari_joystick.h>
@@ -132,8 +133,11 @@ int __init atari_joystick_init(void)
init_waitqueue_head(&joystick[0].wait);
init_waitqueue_head(&joystick[1].wait);
- if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
+ if (devfs_register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
printk("unable to get major %d for joystick devices\n", MAJOR_NR);
+ devfs_register_series (NULL, "joysticks/digital%u", 2, DEVFS_FL_DEFAULT,
+ MAJOR_NR, 128, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &atari_joystick_fops, NULL);
return 0;
}
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 77053421e..7406a8d02 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -1168,7 +1168,7 @@ static void do_stram_request( void )
{
unsigned long start, len;
- while( CURRENT ) {
+ while( !QUEUE_EMPTY ) {
if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
panic("stram: request list destroyed");
if (CURRENT->bh) {
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index ce8260504..5b12f470e 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -161,10 +161,17 @@ if [ "$CONFIG_SCSI" != "n" ]; then
comment 'SCSI support type (disk, tape, CD-ROM)'
dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+ int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+ fi
dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
fi
dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
@@ -273,9 +280,13 @@ if [ "$CONFIG_NET" = "y" ]; then
tristate ' Apollo 3c505 support' CONFIG_APOLLO_ELPLUS
fi
if [ "$CONFIG_MAC" = "y" ]; then
- bool ' Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT
-# bool ' Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE
- bool ' Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC
+ bool ' Macintosh NS 8390 based ethernet cards' CONFIG_MAC8390
+ tristate ' Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)' CONFIG_MACSONIC
+ tristate ' Macintosh SMC 9194 based ethernet cards' CONFIG_SMC9194
+ tristate ' Macintosh CS89x0 based ethernet cards' CONFIG_MAC89x0
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)' CONFIG_MACMACE
+ fi
fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
tristate ' MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET
@@ -352,12 +363,6 @@ if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_BUSMOUSE y
fi
fi
-if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac ADB mouse support' CONFIG_ADBMOUSE
- if [ "$CONFIG_ADBMOUSE" != "n" ]; then
- define_bool CONFIG_BUSMOUSE y
- fi
-fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
tristate 'Atari SCC serial support' CONFIG_ATARI_SCC
@@ -384,7 +389,20 @@ if [ "$CONFIG_PARPORT" = "n" ]; then
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac SCC serial support' CONFIG_MAC_SCC
+ tristate 'Macintosh serial support' CONFIG_MAC_SCC
+ bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
+ if [ "$CONFIG_ADB" = "y" ]; then
+ bool ' Support for ADB keyboard' CONFIG_ADB_KEYBOARD
+ bool ' Support for ADB mouse' CONFIG_ADBMOUSE
+ bool ' Include Mac II ADB driver' CONFIG_ADB_MACII
+ bool ' Include Mac IIsi ADB driver' CONFIG_ADB_MACIISI
+ bool ' Include CUDA ADB driver' CONFIG_ADB_CUDA
+ bool ' Include IOP (IIfx/Quadra 9x0) ADB driver' CONFIG_ADB_IOP
+ bool ' Include PMU (Powerbook) ADB driver' CONFIG_ADB_PMU68K
+ fi
+ if [ "$CONFIG_ADBMOUSE" = "y" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
fi
if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
tristate 'HP DCA serial support' CONFIG_HPDCA
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 6d10ca35f..c51e43802 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -27,6 +27,8 @@ endif
head.o: head.S m68k_defs.h
+entry.o: entry.S m68k_defs.h
+
sun3-head.o: sun3-head.S m68k_defs.h
m68k_defs.h: m68k_defs.c m68k_defs.head
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 021652201..5f08ef216 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -236,12 +236,12 @@ SYMBOL_NAME_LABEL(ret_from_interrupt)
#endif
/* check if we need to do software interrupts */
- movel SYMBOL_NAME(bh_active),%d0
- andl SYMBOL_NAME(bh_mask),%d0
+ movel SYMBOL_NAME(softirq_state),%d0
+ andl SYMBOL_NAME(softirq_state)+4,%d0
jeq SYMBOL_NAME(ret_from_exception)
pea SYMBOL_NAME(ret_from_exception)
- jra SYMBOL_NAME(do_bottom_half)
+ jra SYMBOL_NAME(do_softirq)
/* Handler for uninitialized and spurious interrupts */
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 790d153ab..6f8300422 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -18,7 +18,6 @@
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
-#include <asm/m68kserial.h>
asmlinkage long long __ashrdi3 (long long, int);
asmlinkage long long __lshrdi3 (long long, int);
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 10613c0a4..f50cd262c 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -10,6 +10,6 @@
O_TARGET := mac.o
OX_OBJS := mac_ksyms.o
O_OBJS := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
- macboing.o debug.o misc.o
+ baboon.o macboing.o debug.o misc.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c
deleted file mode 100644
index 23e98c048..000000000
--- a/arch/m68k/mac/adb-bus.c
+++ /dev/null
@@ -1,2699 +0,0 @@
-/*
- * MACII ADB keyboard handler.
- * Copyright (c) 1997 Alan Cox
- *
- * Derived from code
- * Copyright (C) 1996 Paul Mackerras.
- *
- * MSch (9/97) Partial rewrite of interrupt handler to MacII style
- * ADB handshake, based on:
- * - Guide to Mac Hardware
- * - Guido Koerber's session with a logic analyzer
- *
- * MSch (1/98) Integrated start of IIsi driver by Robert Thompson
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include "via6522.h"
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/adb.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/setup.h>
-#include <asm/macintosh.h>
-#include <asm/macints.h>
-
-
-#define MACII /* For now - will be a switch */
-
-/* Bits in B data register: all active low */
-#define TREQ 0x08 /* Transfer request (input) */
-#define TACK 0x10 /* Transfer acknowledge (output) */
-#define TIP 0x20 /* Transfer in progress (output) */
-
-/* Bits in B data register: ADB transaction states MacII */
-#define ST_MASK 0x30 /* mask for selecting ADB state bits */
-/* ADB transaction states according to GMHW */
-#define ST_CMD 0x00 /* ADB state: command byte */
-#define ST_EVEN 0x10 /* ADB state: even data byte */
-#define ST_ODD 0x20 /* ADB state: odd data byte */
-#define ST_IDLE 0x30 /* ADB state: idle, nothing to send */
-
-/* Bits in ACR */
-#define SR_CTRL 0x1c /* Shift register control bits */
-#ifdef USE_ORIG
-#define SR_EXT 0x1c /* Shift on external clock */
-#else
-#define SR_EXT 0x0c /* Shift on external clock */
-#endif
-#define SR_OUT 0x10 /* Shift out if 1 */
-
-/* Bits in IFR and IER */
-#define IER_SET 0x80 /* set bits in IER */
-#define IER_CLR 0 /* clear bits in IER */
-#define SR_INT 0x04 /* Shift register full/empty */
-#define SR_DATA 0x08 /* Shift register data */
-#define SR_CLOCK 0x10 /* Shift register clock */
-
-/* JRT */
-#define ADB_DELAY 150
-
-static struct adb_handler {
- void (*handler)(unsigned char *, int, struct pt_regs *);
-} adb_handler[16];
-
-static enum adb_state {
- idle,
- sent_first_byte,
- sending,
- reading,
- read_done,
- awaiting_reply
-} adb_state;
-
-static struct adb_request *current_req;
-static struct adb_request *last_req;
-static unsigned char cuda_rbuf[16];
-static unsigned char *reply_ptr;
-static int reply_len;
-static int reading_reply;
-static int data_index;
-static int first_byte;
-static int prefix_len;
-
-static int status = ST_IDLE|TREQ;
-static int last_status;
-
-static int driver_running = 0;
-
-/*static int adb_delay;*/
-int in_keybinit = 1;
-
-static void adb_start(void);
-extern void adb_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
-static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs);
-
-static void adb_hw_setup_IIsi(void);
-static void adb_hw_setup_cuda(void);
-
-/*
- * debug level 10 required for ADB logging (should be && debug_adb, ideally)
- */
-
-extern int console_loglevel;
-
-/*
- * Misc. defines for testing - should go to header :-(
- */
-
-#define ADBDEBUG_STATUS (1)
-#define ADBDEBUG_STATE (2)
-#define ADBDEBUG_READ (4)
-#define ADBDEBUG_WRITE (8)
-#define ADBDEBUG_START (16)
-#define ADBDEBUG_RETRY (32)
-#define ADBDEBUG_POLL (64)
-#define ADBDEBUG_INT (128)
-#define ADBDEBUG_PROT (256)
-#define ADBDEBUG_SRQ (512)
-#define ADBDEBUG_REQUEST (1024)
-#define ADBDEBUG_INPUT (2048)
-#define ADBDEBUG_DEVICE (4096)
-
-#define ADBDEBUG_IISI (8192)
-
-
-/*#define DEBUG_ADB*/
-
-#ifdef DEBUG_ADB
-#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
-#else
-#define ADBDEBUG (0)
-#endif
-
-#define TRY_CUDA
-
-void adb_bus_init(void)
-{
- unsigned long flags;
- unsigned char c, i;
-
- save_flags(flags);
- cli();
-
- /*
- * Setup ADB
- */
-
- switch(macintosh_config->adb_type)
- {
-
- case MAC_ADB_II:
- printk("adb: MacII style keyboard/mouse driver.\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
- /*
- * Docs suggest TREQ should be output - that seems nuts
- * BSD agrees here :-)
- * Setup vPCR ??
- */
-
-#ifdef USE_ORIG
- /* Lower the bus signals (MacII is active low it seems ???) */
- via_write(via1, vBufB, via_read(via1, vBufB)&~TACK);
-#else
- /* Corresponding state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- last_status = (via_read(via1, vBufB)&~ST_MASK);
-#endif
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- * hopefully idle (Im assuming the mac didnt leave a half
- * complete transaction on booting us).
- */
-
- request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_interrupt);
- adb_state = idle;
- break;
- /*
- * Unsupported; but later code doesn't notice !!
- */
- case MAC_ADB_CUDA:
- printk("adb: CUDA interface.\n");
-#if 0
- /* don't know what to set up here ... */
- adb_state = idle;
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-#endif
- adb_hw_setup_cuda();
- adb_state = idle;
- request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
- "adb CUDA interrupt", adb_cuda_interrupt);
- break;
- case MAC_ADB_IISI:
- printk("adb: Using IIsi hardware.\n");
- printk("\tDEBUG_JRT\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-
- /*
- * MSch: I'm pretty sure the setup is mildly wrong
- * for the IIsi.
- */
- /* Initial state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) );
- last_status = (via_read(via1, vBufB)&~ST_MASK);
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /* get those pesky clock ticks we missed while booting */
- for ( i = 0; i < 60; i++) {
- udelay(ADB_DELAY);
- adb_hw_setup_IIsi();
- udelay(ADB_DELAY);
- if (via_read(via1, vBufB) & TREQ)
- break;
- }
- if (i == 60)
- printk("adb_IIsi: maybe bus jammed ??\n");
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- */
- request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_cuda_interrupt);
- adb_state = idle;
- break;
- default:
- printk("adb: Unknown hardware interface.\n");
- nosupp:
- printk("adb: Interface unsupported.\n");
- restore_flags(flags);
- return;
- }
-
- /*
- * XXX: interrupt only registered if supported HW !!
- * -> unsupported HW will just time out on keyb_init!
- */
-#if 0
- request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_interrupt);
-#endif
-#ifdef DEBUG_ADB_INTS
- request_irq(IRQ_MAC_ADB_CL, adb_clock_interrupt, IRQ_FLG_LOCK,
- "adb clock interrupt", adb_clock_interrupt);
- request_irq(IRQ_MAC_ADB_SD, adb_data_interrupt, IRQ_FLG_LOCK,
- "adb data interrupt", adb_data_interrupt);
-#endif
-
- printk("adb: init done.\n");
- restore_flags(flags);
-}
-
-void adb_hw_setup_cuda(void)
-{
- int x;
- unsigned long flags;
-
- printk("CUDA: HW Setup:");
-
- save_flags(flags);
- cli();
-
- if (console_loglevel == 10)
- printk(" 1,");
-
- /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */
- via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK );
- via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ );
-
- if (console_loglevel == 10)
- printk("2,");
-
- /* Set the clock control. Set to shift data in by external clock CB1 */
- via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT );
-
- if (console_loglevel == 10)
- printk("3,");
-
- /* Clear any possible Cuda interrupt */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("4,");
-
- /* Terminate transaction and set idle state */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK );
-
- if (console_loglevel == 10)
- printk("5,");
-
- /* Delay 4 mS for ADB reset to complete */
- udelay(4000);
-
- if (console_loglevel == 10)
- printk("6,");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("7,");
- /* Issue a sync transaction, TACK asserted while TIP negated */
- via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK );
-
- if (console_loglevel == 10)
- printk("8,");
-
- /* Wait for the sync acknowledgement, Cuda to assert TREQ */
- while( ( via_read( via1, vBufB ) & TREQ ) != 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("9,");
-
- /* Wait for the sync acknowledment interrupt */
- while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("10,");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("11,");
-
- /* Terminate the sync cycle by negating TACK */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TACK );
-
- if (console_loglevel == 10)
- printk("12,");
-
- /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */
- while( ( via_read( via1, vBufB ) & TREQ ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("13,");
-
- /* Wait for the sync termination acknowledment interrupt */
- while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("14,");
-
- /* Terminate transaction and set idle state, TIP+TACK negate */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TIP );
-
- if (console_loglevel == 10)
- printk("15 !");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- restore_flags(flags);
-
- printk("\nCUDA: HW Setup done!\n");
-}
-
-void adb_hw_setup_IIsi(void)
-{
- int dummy;
- long poll_timeout;
-
- printk("adb_IIsi: cleanup!\n");
-
- /* ??? */
- udelay(ADB_DELAY);
-
- /* disable SR int. */
- via_write(via1, vIER, IER_CLR|SR_INT);
- /* set SR to shift in */
- via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT);
-
- /* this is required, especially on faster machines */
- udelay(ADB_DELAY);
-
- if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */
- /* start frame */
- via_write(via1, vBufB,via_read(via1,vBufB) | TIP);
-
- while (1) {
- /* poll for ADB interrupt and watch for timeout */
- /* if time out, keep going in hopes of not hanging the
- * ADB chip - I think */
- poll_timeout = ADB_DELAY * 5;
- while ( !(via_read(via1, vIFR) & SR_INT)
- && (poll_timeout-- > 0) )
- dummy = via_read(via1, vBufB);
-
- dummy = via_read(via1, vSR); /* reset interrupt flag */
-
- /* perhaps put in a check here that ignores all data
- * after the first ADB_MAX_MSG_LENGTH bytes ??? */
-
- /* end of frame reached ?? */
- if (via_read(via1, vBufB) & TREQ)
- break;
-
- /* set ACK */
- via_write(via1,vBufB,via_read(via1, vBufB) | TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* clear ACK */
- via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK);
- }
- /* end frame */
- via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP);
- /* probably don't need to delay this long */
- udelay(ADB_DELAY);
- }
- /* re-enable SR int. */
- via_write(via1, vIER, IER_SET|SR_INT);
-}
-
-#define WAIT_FOR(cond, what) \
- do { \
- for (x = 1000; !(cond); --x) { \
- if (x == 0) { \
- printk("Timeout waiting for " what); \
- return 0; \
- } \
- __delay(100*160); \
- } \
- } while (0)
-
-/*
- * Construct and send an adb request
- * This function is the main entry point into the ADB driver from
- * kernel code; it takes the request data supplied and populates the
- * adb_request structure.
- * In order to keep this interface independent from any assumption about
- * the underlying ADB hardware, we take requests in CUDA format here,
- * the ADB packet 'prefixed' with a packet type code.
- * Non-CUDA hardware is confused by this, so we strip the packet type
- * here depending on hardware type ...
- */
-int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
- int nbytes, ...)
-{
- va_list list;
- int i, start;
-
- va_start(list, nbytes);
-
- /*
- * skip first byte if not CUDA
- */
- if (macintosh_config->adb_type == MAC_ADB_II) {
- start = va_arg(list, int);
- nbytes--;
- }
- req->nbytes = nbytes;
- req->done = done;
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("adb_request, data bytes: ");
-#endif
- for (i = 0; i < nbytes; ++i) {
- req->data[i] = va_arg(list, int);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("%x ", req->data[i]);
-#endif
- }
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk(" !\n");
-#endif
- va_end(list);
- /*
- * XXX: This might be fatal if no reply is generated (i.e. Listen) !
- * Currently, the interrupt handler 'fakes' a reply on non-TALK
- * commands for this reason.
- * Also, we need a CUDA_AUTOPOLL emulation here for non-CUDA
- * Macs, and some mechanism to remember the last issued TALK
- * request for resending it repeatedly on timeout!
- */
- req->reply_expected = 1;
- return adb_send_request(req);
-}
-
-/*
- * Construct an adb request for later sending
- * This function only populates the adb_request structure, without
- * actually queueing it.
- * Reason: Poll requests and Talk requests need to be handled in a way
- * different from 'user' requests; no reply_expected is set and
- * Poll requests need to be placed at the head of the request queue.
- * Using adb_request results in implicit queueing at the tail of the
- * request queue (duplicating the Poll) with reply_expected set.
- * No adjustment of packet data is necessary, as this mechanisnm is not
- * used by CUDA hardware (Autopoll used instead).
- */
-int adb_build_request(struct adb_request *req, void (*done)(struct adb_request *),
- int nbytes, ...)
-{
- va_list list;
- int i;
-
- req->nbytes = nbytes;
- req->done = done;
- va_start(list, nbytes);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("adb__build_request, data bytes: ");
-#endif
- /*
- * skip first byte if not CUDA ?
- */
- for (i = 0; i < nbytes; ++i) {
- req->data[i] = va_arg(list, int);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("%x ", req->data[i]);
-#endif
- }
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk(" !\n");
-#endif
- va_end(list);
-
- req->reply_expected = 0;
- return 0;
-}
-
-/*
- * Send an ADB poll (Talk, tagged on the front of the request queue)
- */
-void adb_queue_poll(void)
-{
- static int pod=0;
- static int in_poll=0;
- static struct adb_request r;
- unsigned long flags;
-
- if(in_poll)
- printk("Double poll!\n");
-
- in_poll++;
- pod++;
- if(pod>7) /* 15 */
- pod=0;
-
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb: Polling %d\n",pod);
-#endif
-
- if (macintosh_config->adb_type == MAC_ADB_II)
- /* XXX: that's a TALK, register 0, MacII version */
- adb_build_request(&r,NULL, 1, (pod<<4|0xC));
- else
- /* CUDA etc. version */
- adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC));
-
- r.reply_expected=0;
- r.done=NULL;
- r.sent=0;
- r.got_reply=0;
- r.reply_len=0;
- save_flags(flags);
- cli();
- /* Poll inserted at head of queue ... */
- r.next=current_req;
- current_req=&r;
- restore_flags(flags);
- adb_start();
- in_poll--;
-}
-
-/*
- * Send an ADB retransmit (Talk, appended to the request queue)
- */
-void adb_retransmit(int device)
-{
- static int in_retransmit=0;
- static struct adb_request rt;
- unsigned long flags;
-
- if(in_retransmit)
- printk("Double retransmit!\n");
-
- in_retransmit++;
-
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb: Sending retransmit: %d\n", device);
-#endif
-
- /* MacII version */
- adb_build_request(&rt,NULL, 1, (device<<4|0xC));
-
- rt.reply_expected = 0;
- rt.done = NULL;
- rt.sent = 0;
- rt.got_reply = 0;
- rt.reply_len = 0;
- rt.next = NULL;
-
- save_flags(flags);
- cli();
-
- /* Retransmit inserted at tail of queue ... */
-
- if (current_req != NULL)
- {
- last_req->next = &rt;
- last_req = &rt;
- }
- else
- {
- current_req = &rt;
- last_req = &rt;
- }
-
- /* always restart driver (send_retransmit used in place of adb_start!)*/
-
- if (adb_state == idle)
- adb_start();
-
- restore_flags(flags);
- in_retransmit--;
-}
-
-/*
- * Queue an ADB request; start ADB transfer if necessary
- */
-int adb_send_request(struct adb_request *req)
-{
- unsigned long flags;
-
- req->next = 0;
- req->sent = 0;
- req->got_reply = 0;
- req->reply_len = 0;
- save_flags(flags);
- cli();
-
- if (current_req != NULL)
- {
- last_req->next = req;
- last_req = req;
- }
- else
- {
- current_req = req;
- last_req = req;
- if (adb_state == idle)
- adb_start();
- }
-
- restore_flags(flags);
- return 0;
-}
-
-static int nclock, ndata;
-
-static int need_poll = 0;
-static int command_byte = 0;
-static int last_reply = 0;
-static int last_active = 0;
-
-static struct adb_request *retry_req;
-
-/*
- * Start sending ADB packet
- */
-static void adb_start(void)
-{
- unsigned long flags;
- struct adb_request *req;
-
- /*
- * We get here on three 'sane' conditions:
- * 1) called from send_adb_request, if adb_state == idle
- * 2) called from within adb_interrupt, if adb_state == idle
- * (after receiving, or after sending a LISTEN)
- * 3) called from within adb_interrupt, if adb_state == sending
- * and no reply is expected (immediate next command).
- * Maybe we get here on SRQ as well ??
- */
-
- /* get the packet to send */
- req = current_req;
- /* assert adb_state == idle */
- if (adb_state != idle) {
- printk("ADB: adb_start called while driver busy (%p %x %x)!\n",
- req, adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
- return;
- }
- if (req == 0)
- return;
- save_flags(flags);
- cli();
-
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("adb_start: request %p ", req);
-#endif
-
- nclock = 0;
- ndata = 0;
-
- /*
- * IRQ signaled ?? (means ADB controller wants to send, or might
- * be end of packet if we were reading)
- */
- if ((via_read(via1, vBufB) & TREQ) == 0)
- {
- switch(macintosh_config->adb_type)
- {
- /*
- * FIXME - we need to restart this on a timer
- * or a collision at boot hangs us.
- * Never set adb_state to idle here, or adb_start
- * won't be called again from send_request!
- * (need to re-check other cases ...)
- */
- case MAC_ADB_CUDA:
- /* printk("device busy - fail\n"); */
- restore_flags(flags);
- /* a byte is coming in from the CUDA */
- return;
- case MAC_ADB_IISI:
- printk("adb_start: device busy - fail\n");
- retry_req = req;
- restore_flags(flags);
- return;
- case MAC_ADB_II:
- /*
- * if the interrupt handler set the need_poll
- * flag, it's hopefully a SRQ poll or re-Talk
- * so we try to send here anyway
- */
- if (!need_poll) {
- printk("device busy - retry %p state %d status %x!\n",
- req, adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
- retry_req = req;
- /* set ADB status here ? */
- restore_flags(flags);
- return;
- } else {
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("device busy - polling; state %d status %x!\n",
- adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
-#endif
- need_poll = 0;
- break;
- }
- }
- }
-
-#if 0
- /*
- * Bus idle ?? Not sure about this one; SRQ might need ST_CMD here!
- * OTOH: setting ST_CMD in the interrupt routine would make the
- * ADB contoller shift in before this routine starts shifting out ...
- */
- if ((via_read(via1, vBufB)&ST_MASK) != ST_IDLE)
- {
-#if (ADBDEBUG & ADBDEBUG_STATE)
- if (console_loglevel == 10)
- printk("ADB bus not idle (%x), retry later!\n",
- via_read(via1, vBufB)&(ST_MASK|TREQ));
-#endif
- retry_req = req;
- restore_flags(flags);
- return;
- }
-#endif
-
- /*
- * Another retry pending? (sanity check)
- */
- if (retry_req) {
-#if (ADBDEBUG & ADBDEBUG_RETRY)
- if (console_loglevel == 10)
- if (retry_req == req)
- /* new requests are appended at tail of request queue */
- printk("adb_start: retry %p pending ! \n", req);
- else
- /* poll requests are added to the head of queue */
- printk("adb_start: retry %p pending, req %p (poll?) current! \n",
- retry_req, req);
-#endif
- retry_req = NULL;
- }
-
- /*
- * Seems OK, go for it!
- */
- switch(macintosh_config->adb_type)
- {
- case MAC_ADB_CUDA:
- /* store command byte (first byte is 'type' byte) */
- command_byte = req->data[1];
- /* set the shift register to shift out and send a byte */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- via_write(via1, vSR, req->data[0]);
- via_write(via1, vBufB, via_read(via1, vBufB)&~TIP);
- break;
- case MAC_ADB_IISI:
- /* store command byte (first byte is 'type' byte) */
- command_byte = req->data[1];
- /* set ADB state to 'active' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* switch ACK off (in case it was left on) */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* set the shift register to shift out and send a byte */
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
- via_write(via1, vSR, req->data[0]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- break;
- case MAC_ADB_II:
- /* store command byte */
- command_byte = req->data[0];
- /* Output mode */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* Load data */
- via_write(via1, vSR, req->data[0]);
-#ifdef USE_ORIG
- /* Turn off TIP/TACK - this should tell the external logic to
- start the external shift clock */
-/* via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));*/
- via_write(via1, vBufB, via_read(via1, vBufB)|(TIP|TACK));
-#else
- /* set ADB state to 'command' */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_CMD);
-#endif
- break;
- }
- adb_state = sent_first_byte;
- data_index = 1;
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("sent first byte of %d: %x, (%x %x) ... ",
- req->nbytes, req->data[0], adb_state,
- (via_read(via1, vBufB) & (ST_MASK|TREQ)) );
-#endif
- restore_flags(flags);
-}
-
-/*
- * Poll the ADB state (maybe obsolete now that interrupt-driven ADB runs)
- */
-void adb_poll(void)
-{
- unsigned char c;
- unsigned long flags;
- save_flags(flags);
- cli();
- c=via_read(via1, vIFR);
-#if (ADBDEBUG & ADBDEBUG_POLL)
-#ifdef DEBUG_ADB_INTS
- if (console_loglevel == 10) {
- printk("adb_poll: IFR %x state %x cl %d dat %d ",
- c, adb_state, nclock, ndata);
- if (c & (SR_CLOCK|SR_DATA)) {
- if (c & SR_CLOCK)
- printk("adb clock event ");
- if (c & SR_DATA)
- printk("adb data event ");
- }
- }
-#else
- if (console_loglevel == 10)
- printk("adb_poll: IFR %x state %x ",
- c, adb_state);
-#endif
- if (console_loglevel == 10)
- printk("\r");
-#endif
- if (c & SR_INT)
- {
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb_poll: adb interrupt event\n");
-#endif
- adb_interrupt(0, 0, 0);
- }
- restore_flags(flags);
-}
-
-/*
- * Debugging gimmicks
- */
-void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- nclock++;
-}
-
-void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- ndata++;
-}
-
-/*
- * The notorious ADB interrupt handler - does all of the protocol handling,
- * except for starting new send operations. Relies heavily on the ADB
- * controller sending and receiving data, thereby generating SR interrupts
- * for us. This means there has to be always activity on the ADB bus, otherwise
- * the whole process dies and has to be re-kicked by sending TALK requests ...
- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
- * a good choice; either on timeout or on a timer interrupt).
- *
- * The basic ADB state machine was left unchanged from the original MacII code
- * by Alan Cox, which was based on the CUDA driver for PowerMac.
- * The syntax of the ADB status lines seems to be totally different on MacII,
- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start
- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on
- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the
- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB
- * protocol with a logic analyzer!!)
- * CUDA seems to use /TIP -> /TIP | TACK -> /TIP -> /TIP | TACK ... -> TIP|TACK
- * for sending, and /TIP -> /TIP | TACK -> /TIP -> /TIP | TACK ... -> TIP for
- * receiving. No clue how timeouts are handled; SRQ seems to be sent as a
- * separate packet. Quite a few changes have been made outside the handshake
- * code, so I don't know if the CUDA code still behaves as before.
- *
- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
- * and retransmit (Talk to the last active device). Cleanup of code and
- * testing of the CUDA functionality is required, though.
- * Note2: As of 13/12/97, CUDA support is definitely broken ...
- * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption
- * that Q700 and Q800 use CUDA :-(
- *
- * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the
- * initial bits). See adb_cuda_interrupts ...
- *
- * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG
- * conditionals can be a start?)
- */
-void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- int x, adbdir;
- unsigned long flags;
- struct adb_request *req;
-
- last_status = status;
-
- /* prevent races due to SCSI enabling ints */
- save_flags(flags);
- cli();
-
- if (driver_running) {
- restore_flags(flags);
- return;
- }
-
- driver_running = 1;
-
-#ifdef USE_ORIG
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
-#else
- if (macintosh_config->adb_type==MAC_ADB_CUDA)
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
- else
- /* status bits (0x8->0x20) and direction (0x10 ??) CLASH !! */
- status = (via_read(via1, vBufB) & (ST_MASK|TREQ));
-#endif
- adbdir = (via_read(via1, vACR) & SR_OUT);
-#if (ADBDEBUG & ADBDEBUG_INT)
- if (console_loglevel == 10)
- printk("adb_interrupt: state=%d status=%x last=%x direction=%x\n",
- adb_state, status, last_status, adbdir);
-#endif
-
- switch (adb_state)
- {
- case idle:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data - unsolicited */
- if (status != TREQ)
- printk("cuda: state=idle, status=%x\n", status);
- x = via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- udelay(150);
- /* set SR to IN (??? no byte received else) */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status == TREQ && !adbdir)
- /* that's: not IRQ, idle, input -> weird */
- printk("adb_macII: idle, status=%x dir=%x\n",
- status, adbdir);
-#endif
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macII: receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* set ADB state = even for first data byte */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- }
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- reading_reply = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = first_byte;
- *reply_ptr++ = command_byte; /*first_byte;*/
- reply_len = 3;
- prefix_len = 3;
- }
- break;
-
- case awaiting_reply:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data of a reply */
- if (status != TREQ)
- printk("cuda: state=awaiting_reply, status=%x\n", status);
- x = via_read(via1, vSR);
- via_write(via1,vBufB,
- via_read(via1, vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macIIsi: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
-#if 0
- if( via_read(via1,vBufB) & TREQ)
- ending = 1;
- else
- ending = 0;
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /* handshake etc. for II ?? */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macII: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* set ADB state = even for first data byte */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- }
- adb_state = reading;
- reply_ptr = current_req->reply;
- reading_reply = 1;
- reply_len = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = first_byte;
- *reply_ptr++ = first_byte; /* should be command byte */
- reply_len = 3;
- prefix_len = 3;
- }
- break;
-
- case sent_first_byte:
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" sending: %x (%x %x) ",
- current_req->data[1], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TREQ + TIP + SR_OUT)
- {
- /* collision */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TIP|TACK);
- adb_state = idle;
- }
- else
- {
- /* assert status == TIP + SR_OUT */
- if (status != TIP + SR_OUT)
- printk("cuda: state=sent_first_byte status=%x\n", status);
- via_write(via1,vSR,current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index = 2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- if ( !(via_read(via1, vBufB) & TREQ) )
- {
- /* collision */
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("adb_macIIsi: send collison, aborting!\n");
-#endif
- /* set shift in */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state to 'idle' */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TIP|TACK));
- adb_state = idle;
- }
- else
- {
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
-#endif
- via_write(via1, vSR, current_req->data[1]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- data_index=2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /* how to detect a collision here ?? */
- /* maybe we're already done (Talk, or Poll)? */
- if (data_index >= current_req->nbytes)
- {
- /* assert it's a Talk ?? */
- if ( (command_byte&0xc) != 0xc
- && console_loglevel == 10 )
- printk("ADB: single byte command, no Talk: %x!\n",
- command_byte);
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index, current_req->nbytes, adb_state, status);
-#endif
- current_req->sent = 1;
- if (current_req->reply_expected)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("ADB: reply expected on poll!\n");
-#endif
- adb_state = awaiting_reply;
- reading_reply = 0;
- } else {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("ADB: no reply for poll, not calling done()!\n");
-#endif
- req = current_req;
- current_req = req->next;
-#if 0 /* XXX Not sure about that one ... probably better enabled */
- if (req->done)
- (*req->done)(req);
-#endif
- adb_state = idle;
- reading_reply = 0;
- }
- /* set to shift in */
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- /* set ADB state idle - might get SRQ */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- break;
- }
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(!(status==(ST_CMD|TREQ) && adbdir == SR_OUT))
- printk("adb_macII: sent_first_byte, weird status=%x dir=%x\n",
- status, adbdir);
-#endif
- /* SR already set to shift out; send byte */
- via_write(via1, vSR, current_req->data[1]);
- /* set state to ST_EVEN (first byte was: ST_CMD) */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- data_index=2;
- adb_state = sending;
- }
- break;
-
- case sending:
- req = current_req;
- if (data_index >= req->nbytes)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index-1, req->nbytes, adb_state, status);
-#endif
- /* end of packet */
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TACK|TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* XXX maybe clear ACK here ??? */
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift in */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state 'idle' (end of frame) */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TACK|TIP));
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /*
- * XXX Not sure: maybe only switch to
- * input mode on Talk ??
- */
- /* set to shift in */
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- /* set ADB state idle - might get SRQ */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- }
- req->sent = 1;
- if (req->reply_expected)
- {
- /*
- * maybe fake a reply here on Listen ??
- * Otherwise, a Listen hangs on success
- */
- if ( macintosh_config->adb_type==MAC_ADB_II
- && ((req->data[0]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else if ( macintosh_config->adb_type != MAC_ADB_II
- && ( req->data[0] == 0x0)
- && ((req->data[1]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else {
- /*
- * Reply expected, but none
- * possible -> fake reply.
- * Problem: sending next command
- * should probably be done
- * without setting bus to 'idle'!
- * (except if no more commands)
- */
-#if (ADBDEBUG & ADBDEBUG_PROT)
- printk("ADB: reply expected on Listen, faking reply\n");
-#endif
- /* make it look weird */
- /* XXX: return reply_len -1? */
- /* XXX: fake ADB header? */
- req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
- req->reply_len = 3;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /*
- * ready with this one, run
- * next command or repeat last
- * Talk (=idle on II)
- */
- /* set state to idle !! */
- adb_state = idle;
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /* not sure about this */
- /*
- * MS: Must set idle, no new request
- * started else !
- */
- adb_state = idle;
- /*
- * requires setting ADB state to idle,
- * maybe read a byte ! (done above)
- */
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- req->data[data_index], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* XXX: need to check for collision?? */
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
-#endif
- via_write(via1, vSR, req->data[data_index++]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vSR, req->data[data_index++]);
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
- }
- }
- break;
-
- case reading:
-
- /* timeout / SRQ handling for II hw */
-#ifdef POLL_ON_TIMEOUT
- if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
-#else
- if( (first_byte == 0xFF && (reply_len-prefix_len)==2
- && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) ||
- ((reply_len-prefix_len)==3
- && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
-#endif
- {
- /*
- * possible timeout (in fact, most probably a
- * timeout, since SRQ can't be signaled without
- * transfer on the bus).
- * The last three bytes seen were FF, together
- * with the starting byte (in case we started
- * on 'idle' or 'awaiting_reply') this probably
- * makes four. So this is mostl likely #5!
- * The timeout signal is a pattern 1 0 1 0 0..
- * on /INT, meaning we missed it :-(
- */
- x = via_read(via1, vSR);
- if (x != 0xFF)
- printk("ADB: mistaken timeout/SRQ!\n");
-
- /*
- * ADB status bits: either even or odd.
- * adb_state: need to set 'idle' here.
- * Maybe saner: set 'need_poll' or
- * 'need_resend' here, fall through to
- * read_done ??
- */
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" -> read aborted: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
-
-#if 0 /* XXX leave status unchanged!! - need to check this again! */
- /* XXX Only touch status on II !!! */
- /* set ADB state to idle (required by adb_start()) */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
-
- /*
- * What if the timeout happens on reading a
- * reply ?? Assemble error reply and call
- * current_request->done()? Keep request
- * on queue?
- */
-
- /* prevent 'busy' in adb_start() */
- need_poll = 1;
-
- /*
- * Timeout: /IRQ alternates high/low during
- * 4 'FF' bytes (1 0 1 0 0...)
- * We're on byte 5, so we need one
- * more backlog here (TBI) ....
- */
- if ((status&TREQ) != (last_status&TREQ)) {
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("ADB: reply timeout, resending!\n");
-#endif
- /*
- * first byte received should be the
- * command byte timing out !!
- */
- if (first_byte != 0xff)
- command_byte = first_byte;
-
- /*
- * compute target for retransmit: if
- * last_active is set, use that one,
- * else use command_byte
- */
- if (last_active == -1)
- last_active = (command_byte&0xf0)>>4;
- adb_state = idle;
- /* resend if TALK, don't poll! */
- if (current_req)
- adb_start();
- else
- /*
- * XXX: need to count the timeouts ??
- * restart last active TALK ??
- * If no current_req, reuse old one!
- */
- adb_retransmit(last_active);
-
- } else {
- /*
- * SRQ: NetBSD suggests /IRQ is asserted!?
- */
- if (status&TREQ)
- printk("ADB: SRQ signature w/o /INT!\n");
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("ADB: empty SRQ packet!\n");
-#endif
- /* Terminate the SRQ packet and poll */
- adb_state = idle;
- adb_queue_poll();
- }
- /*
- * Leave ADB status lines unchanged (means /IRQ
- * will still be low when entering adb_start!)
- */
- break;
- }
- /* end timeout / SRQ handling for II hw. */
- if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
- {
- /* SRQ tacked on data packet */
- /* Check /IRQ here ?? */
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("\nADB: Packet with SRQ!\n");
-#endif
- /* Terminate the packet (SRQ never ends) */
- x = via_read(via1, vSR);
- adb_state = read_done;
- reply_len -= 3;
- reply_ptr -= 3;
- need_poll = 1;
- /* need to continue; next byte not seen else */
- /*
- * XXX: not at all sure here; maybe need to
- * send away the reply and poll immediately?
- */
- } else {
- /* Sanity check */
- if(reply_len>15)
- reply_len=0;
- /* read byte */
- *reply_ptr = via_read(via1, vSR);
- x = *reply_ptr;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- *reply_ptr, adb_state, status);
-#endif
- reply_ptr++;
- reply_len++;
- }
- /* The usual handshake ... */
- if (macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TIP)
- {
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
- /* assert status == TIP | TREQ */
- if (status != TIP + TREQ)
- printk("cuda: state=reading status=%x\n", status);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* ACK adb chip (maybe check for end first?) */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* end of frame?? */
- if (status & TREQ)
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: end of frame!\n");
-#endif
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB) & ~(TACK|TIP));
- adb_state = read_done;
- /* maybe process read_done here?? Handshake anyway?? */
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_II)
- {
- /*
- * NetBSD hints that the next to last byte
- * is sent with IRQ !!
- * Guido found out it's the last one (0x0),
- * but IRQ should be asserted already.
- * Problem with timeout detection: First
- * transition to /IRQ might be second
- * byte of timeout packet!
- * Timeouts are signaled by 4x FF.
- */
- if(!(status&TREQ) && x == 0x00) /* != 0xFF */
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" -> read done!\n");
-#endif
-#if 0 /* XXX: we take one more byte (why?), so handshake! */
- /* set ADB state to idle */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#else
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
-#endif
- /* adjust packet length */
- reply_len--;
- reply_ptr--;
- adb_state = read_done;
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(status!=TIP+TREQ)
- printk("macII_adb: state=reading status=%x\n", status);
-#endif
- /* not caught: ST_CMD */
- /* required for re-entry 'reading'! */
- if ((status&ST_MASK) == ST_IDLE) {
- /* (in)sanity check - set even */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- } else {
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
- }
- }
- }
- break;
-
- case read_done:
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("ADB: read done: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
- if (reading_reply)
- {
- req = current_req;
- req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- }
- else
- {
- adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
- }
-
- /*
- * remember this device ID; it's the latest we got a
- * reply from!
- */
- last_reply = command_byte;
- last_active = (command_byte&0xf0)>>4;
-
- /*
- * Assert status = ST_IDLE ??
- */
- /*
- * SRQ seen before, initiate poll now
- */
- if (need_poll) {
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("ADB: initiate poll!\n");
-#endif
- adb_state = idle;
- /*
- * set ADB status bits?? (unchanged above!)
- */
- adb_queue_poll();
- need_poll = 0;
- /* hope this is ok; queue_poll runs adb_start */
- break;
- }
-
- /*
- * /IRQ seen, so the ADB controller has data for us
- */
- if (!(status&TREQ))
- {
- /* set ADB state to idle */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = command_byte;
- reply_len = 2;
- prefix_len = 2;
- }
- reading_reply = 0;
- }
- else
- {
- /*
- * no IRQ, send next packet or wait
- */
- adb_state = idle;
- if (current_req)
- adb_start();
- else
- adb_retransmit(last_active);
- }
- break;
-
- default:
-#if (ADBDEBUG & ADBDEBUG_STATE)
- printk("adb_interrupt: unknown adb_state %d?\n", adb_state);
-#endif
- }
- /* reset mutex and interrupts */
- driver_running = 0;
- restore_flags(flags);
-}
-
-/*
- * Restart of CUDA support: please modify this interrupt handler while
- * working at the Quadra etc. ADB driver. We can try to merge them later, or
- * remove the CUDA stuff from the MacII handler
- *
- * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert
- * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely
- * related than to the MacII code, so merging all three might be a bad
- * idea.
- */
-
-void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- int x, status;
- struct adb_request *req;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
- else
- status = via_read(via1, vBufB) & (TIP|TREQ);
-
-#if (ADBDEBUG & ADBDEBUG_INT)
- if (console_loglevel == 10)
- printk("adb_interrupt: state=%d status=%x\n", adb_state, status);
-#endif
-
- switch (adb_state)
- {
- case idle:
- first_byte = 0;
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- /* CUDA has sent us the first byte of data - unsolicited */
- if (status != TREQ)
- printk("cuda: state=idle, status=%x want=%x\n",
- status, TREQ);
-#endif
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_cuda: receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- udelay(150);
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if (status != TREQ)
- printk("adb_macII: state=idle status=%x want=%x\n",
- status, TREQ);
- x = via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
- }
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- reading_reply = 0;
- break;
-
- case awaiting_reply:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data of a reply */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TREQ)
- printk("cuda: state=awaiting_reply, status=%x want=%x\n",
- status, TREQ);
-#endif
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_cuda: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
- via_write(via1,vBufB,
- via_read(via1, vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* udelay(150);*/
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
-#if 0
- if( via_read(via1,vBufB) & TREQ)
- ending = 1;
- else
- ending = 0;
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- adb_state = reading;
- reply_ptr = current_req->reply;
- reading_reply = 1;
- reply_len = 0;
- break;
-
- case sent_first_byte:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" sending: %x (%x %x) ",
- current_req->data[1], adb_state, status);
-#endif
- if (status == TREQ + TIP + SR_OUT)
- {
- /* collision */
- if (console_loglevel == 10)
- printk("adb_cuda: send collision!\n");
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TIP|TACK);
- adb_state = idle;
- }
- else
- {
- /* assert status == TIP + SR_OUT */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TIP + SR_OUT)
- printk("adb_cuda: state=sent_first_byte status=%x want=%x\n",
- status, TIP + SR_OUT);
-#endif
- via_write(via1,vSR,current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index = 2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- if ( !(via_read(via1, vBufB) & TREQ) )
- {
- /* collision */
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("adb_macIIsi: send collison, aborting!\n");
-#endif
- /* set shift in */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state to 'idle' */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TIP|TACK));
- adb_state = idle;
- }
- else
- {
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
-#endif
- via_write(via1, vSR, current_req->data[1]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- data_index=2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if(status!=TIP+SR_OUT)
- printk("adb_macII: state=send_first_byte status=%x want=%x\n",
- status, TIP+SR_OUT);
- via_write(via1, vSR, current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index=2;
- adb_state = sending;
- }
- break;
-
- case sending:
- req = current_req;
- if (data_index >= req->nbytes)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index-1, req->nbytes, adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TACK|TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* XXX maybe clear ACK here ??? */
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift in */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state 'idle' (end of frame) */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TACK|TIP));
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- }
- req->sent = 1;
- if (req->reply_expected)
- {
- /*
- * maybe fake a reply here on Listen ??
- * Otherwise, a Listen hangs on success
- * CUDA+IIsi: only ADB Talk considered
- * RTC/PRAM read (0x1 0x3) to follow.
- */
- if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else {
- /*
- * Reply expected, but none
- * possible -> fake reply.
- */
-#if (ADBDEBUG & ADBDEBUG_PROT)
- printk("ADB: reply expected on Listen, faking reply\n");
-#endif
- /* make it look weird */
- /* XXX: return reply_len -1? */
- /* XXX: fake ADB header? */
- req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
- req->reply_len = 3;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /*
- * ready with this one, run
- * next command !
- */
- /* set state to idle !! */
- adb_state = idle;
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /* not sure about this */
- adb_state = idle;
- adb_start();
- }
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- req->data[data_index], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* XXX: need to check for collision?? */
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
-#endif
- via_write(via1, vSR, req->data[data_index++]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- break;
-
- case reading:
- if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
- {
- /* Terminate the SRQ packet */
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("adb: Got an SRQ\n");
-#endif
- adb_state = idle;
- adb_queue_poll();
- break;
- }
- /* Sanity check - botched in orig. code! */
- if(reply_len>15) {
- printk("adb_cuda: reply buffer overrun!\n");
- /* wrap buffer */
- reply_len=0;
- if (reading_reply)
- reply_ptr = current_req->reply;
- else
- reply_ptr = cuda_rbuf;
- }
- *reply_ptr = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- *reply_ptr, adb_state, status);
-#endif
- reply_ptr++;
- reply_len++;
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TIP)
- {
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
- /* assert status == TIP | TREQ */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TIP + TREQ)
- printk("cuda: state=reading status=%x want=%x\n",
- status, TIP + TREQ);
-#endif
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* ACK adb chip (maybe check for end first?) */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* end of frame?? */
- if (status & TREQ)
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: end of frame!\n");
-#endif
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB) & ~(TACK|TIP));
- adb_state = read_done;
- /* XXX maybe process read_done here??
- Handshake anyway?? */
- }
- }
- if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if( status == TIP)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(status!=TIP+TREQ)
- printk("macII_adb: state=reading status=%x\n", status);
-#endif
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- /* fall through for IIsi on end of frame */
- if (macintosh_config->adb_type != MAC_ADB_IISI
- || adb_state != read_done)
- break;
-
- case read_done:
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb: read done: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
- if (reading_reply)
- {
- req = current_req;
- req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- }
- else
- {
- adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
- }
-
- if (macintosh_config->adb_type==MAC_ADB_CUDA
- && status & TREQ)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)&~TIP);
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reading_reply = 0;
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI
- && !(status & TREQ))
- {
- udelay(150);
- via_write(via1, vBufB,
- via_read(via1, vBufB) | TIP);
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reading_reply = 0;
- }
- else
- {
- adb_state = idle;
- adb_start();
- }
- break;
-
- default:
- printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state);
- }
-
- restore_flags(flags);
-
-}
-
-/*
- * The 'reply delivery' routine; determines which device sent the
- * request and calls the appropriate handler.
- * Reply data are expected in CUDA format (again, argh...) so we need
- * to fake this in the interrupt handler for MacII.
- * Only one handler per device ID is currently possible.
- * XXX: is the ID field here representing the default or real ID?
- */
-static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs)
-{
- int i, id;
-
- switch (buf[0])
- {
- case ADB_PACKET:
- /* what's in buf[1] ?? */
- id = buf[2] >> 4;
-#if 0
- xmon_printf("adb packet: ");
- for (i = 0; i < nb; ++i)
- xmon_printf(" %x", buf[i]);
- xmon_printf(", id = %d\n", id);
-#endif
-#if (ADBDEBUG & ADBDEBUG_INPUT)
- if (console_loglevel == 10) {
- printk("adb_input: adb packet ");
- for (i = 0; i < nb; ++i)
- printk(" %x", buf[i]);
- printk(", id = %d\n", id);
- }
-#endif
- if (adb_handler[id].handler != 0)
- {
- (*adb_handler[id].handler)(buf, nb, regs);
- }
- break;
-
- default:
-#if (ADBDEBUG & ADBDEBUG_INPUT)
- if (console_loglevel == 10) {
- printk("adb_input: data from via (%d bytes):", nb);
- for (i = 0; i < nb; ++i)
- printk(" %.2x", buf[i]);
- printk("\n");
- }
-#endif
- }
-}
-
-/* Ultimately this should return the number of devices with
- the given default id. */
-
-int adb_register(int default_id,
- void (*handler)(unsigned char *, int, struct pt_regs *))
-{
- if (adb_handler[default_id].handler != 0)
- panic("Two handlers for ADB device %d\n", default_id);
- adb_handler[default_id].handler = handler;
- return 1;
-}
-
-/*
- * /dev/adb device driver.
- */
-
-#define ADB_MAJOR 56 /* major number for /dev/adb */
-
-#define ADB_MAX_MINOR 64 /* range of ADB minors */
-#define ADB_TYPE_SHIFT 4 /* # bits for device ID/type in subdevices */
-
-#define ADB_TYPE_RAW 0 /* raw device; unbuffered */
-#define ADB_TYPE_BUFF 1 /* raw device; buffered */
-#define ADB_TYPE_COOKED 2 /* 'cooked' device */
-
-
-extern void adbdev_init(void);
-
-struct adbdev_state {
- struct adb_request req;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
-
-static int adb_wait_reply(struct adbdev_state *state, struct file *file)
-{
- int ret = 0;
- DECLARE_WAITQUEUE(wait,current);
-
- __set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&adb_wait, &wait);
-
- while (!state->req.got_reply) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- schedule();
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&adb_wait, &wait);
-
- return ret;
-}
-
-static void adb_write_done(struct adb_request *req)
-{
- if (!req->got_reply) {
- req->reply_len = 0;
- req->got_reply = 1;
- }
- wake_up_interruptible(&adb_wait);
-}
-
-struct file_operations *adb_raw[16];
-struct file_operations *adb_buffered[16];
-struct file_operations *adb_cooked[16];
-
-static int adb_open(struct inode *inode, struct file *file)
-{
- int adb_type, adb_subtype;
- struct adbdev_state *state;
-
- if (MINOR(inode->i_rdev) > ADB_MAX_MINOR)
- return -ENXIO;
-
- switch (MINOR(inode->i_rdev) >> ADB_TYPE_SHIFT) {
- case ADB_TYPE_RAW:
- /* see code below */
- break;
- case ADB_TYPE_BUFF:
- /* TBI */
- return -ENXIO;
- case ADB_TYPE_COOKED:
- /* subtypes such as kbd, mouse, ... */
- adb_subtype = MINOR(inode->i_rdev) & ~ADB_TYPE_SHIFT;
- if ((file->f_op = adb_cooked[adb_subtype]))
- return file->f_op->open(inode,file);
- else
- return -ENODEV;
- }
-
- state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
- if (state == 0)
- return -ENOMEM;
- file->private_data = state;
- state->req.reply_expected = 0;
- return 0;
-}
-
-static void adb_release(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state = file->private_data;
-
- if (state) {
- file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
- if (adb_wait_reply(state, file))
- return;
- kfree(state);
- }
- return;
-}
-
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
-{
- return -ESPIPE;
-}
-
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2)
- return -EINVAL;
- if (count > sizeof(state->req.reply))
- count = sizeof(state->req.reply);
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
-
- if (!state->req.reply_expected)
- return 0;
-
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
-
- state->req.reply_expected = 0;
- ret = state->req.reply_len;
- copy_to_user(buf, state->req.reply, ret);
-
- return ret;
-}
-
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
-{
- int ret, i;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2 || count > sizeof(state->req.data))
- return -EINVAL;
- ret = verify_area(VERIFY_READ, buf, count);
- if (ret)
- return ret;
-
- if (state->req.reply_expected && !state->req.got_reply) {
- /* A previous request is still being processed.
- Wait for it to finish. */
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
- }
-
- state->req.nbytes = count;
- state->req.done = adb_write_done;
- state->req.got_reply = 0;
- copy_from_user(state->req.data, buf, count);
-#if 0
- switch (adb_hardware) {
- case ADB_NONE:
- return -ENXIO;
- case ADB_VIACUDA:
- state->req.reply_expected = 1;
- cuda_send_request(&state->req);
- break;
- default:
-#endif
- if (state->req.data[0] != ADB_PACKET)
- return -EINVAL;
- for (i = 1; i < state->req.nbytes; ++i)
- state->req.data[i] = state->req.data[i+1];
- state->req.reply_expected =
- ((state->req.data[0] & 0xc) == 0xc);
- adb_send_request(&state->req);
-#if 0
- break;
- }
-#endif
-
- return count;
-}
-
-static struct file_operations adb_fops = {
- llseek: adb_lseek,
- read: adb_read,
- write: adb_write,
- open: adb_open,
- release: adb_release,
-};
-
-int adbdev_register(int subtype, struct file_operations *fops)
-{
- if (subtype < 0 || subtype > 15)
- return -EINVAL;
- if (adb_cooked[subtype])
- return -EBUSY;
- adb_cooked[subtype] = fops;
- return 0;
-}
-
-int adbdev_unregister(int subtype)
-{
- if (subtype < 0 || subtype > 15)
- return -EINVAL;
- if (!adb_cooked[subtype])
- return -ENODEV;
- adb_cooked[subtype] = NULL;
- return 0;
-}
-
-void adbdev_init()
-{
- if (register_chrdev(ADB_MAJOR, "adb", &adb_fops))
- printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
-}
-
-
-#if 0 /* old ADB device */
-
-/*
- * Here are the file operations we export for /dev/adb.
- */
-
-#define ADB_MINOR 140 /* /dev/adb is c 10 140 */
-
-extern void adbdev_inits(void);
-
-struct adbdev_state {
- struct adb_request req;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
-
-static int adb_wait_reply(struct adbdev_state *state, struct file *file)
-{
- int ret = 0;
- DECLARE_WAITQUEUE(wait, current);
-
-#if (ADBDEBUG & ADBDEBUG_DEVICE)
- printk("ADB request: wait_reply (blocking ... \n");
-#endif
-
- __set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&adb_wait, &wait);
-
- while (!state->req.got_reply) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- schedule();
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&adb_wait, &wait);
-
- return ret;
-}
-
-static void adb_write_done(struct adb_request *req)
-{
- if (!req->got_reply) {
- req->reply_len = 0;
- req->got_reply = 1;
- }
- wake_up_interruptible(&adb_wait);
-}
-
-static int adb_open(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state;
-
- state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
- if (state == 0)
- return -ENOMEM;
- file->private_data = state;
- state->req.reply_expected = 0;
- return 0;
-}
-
-static void adb_release(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state = file->private_data;
-
- if (state) {
- file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
- if (adb_wait_reply(state, file))
- return;
- kfree(state);
- }
- return;
-}
-
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
-{
- return -ESPIPE;
-}
-
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2)
- return -EINVAL;
- if (count > sizeof(state->req.reply))
- count = sizeof(state->req.reply);
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
-
- if (!state->req.reply_expected)
- return 0;
-
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
-
- ret = state->req.reply_len;
- memcpy_tofs(buf, state->req.reply, ret);
- state->req.reply_expected = 0;
-
- return ret;
-}
-
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2 || count > sizeof(state->req.data))
- return -EINVAL;
- ret = verify_area(VERIFY_READ, buf, count);
- if (ret)
- return ret;
-
- if (state->req.reply_expected && !state->req.got_reply) {
- /* A previous request is still being processed.
- Wait for it to finish. */
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
- }
-
- state->req.nbytes = count;
- state->req.done = adb_write_done;
- memcpy_fromfs(state->req.data, buf, count);
- state->req.reply_expected = 1;
- state->req.got_reply = 0;
- adb_send_request(&state->req);
-
- return count;
-}
-
-static struct file_operations adb_fops = {
- llseek: adb_lseek,
- read: adb_read,
- write: adb_write,
- open: adb_open,
- release: adb_release,
-};
-
-static struct miscdevice adb_dev = {
- ADB_MINOR,
- "adb",
- &adb_fops
-};
-
-void adbdev_init(void)
-{
- misc_register(&adb_dev);
-}
-
-#endif /* old ADB device */
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
new file mode 100644
index 000000000..445a99780
--- /dev/null
+++ b/arch/m68k/mac/baboon.c
@@ -0,0 +1,124 @@
+/*
+ * Baboon Custom IC Managment
+ *
+ * The Baboon custom IC controls the IDE, PCMCIA and media bay on the
+ * PowerBook 190. It multiplexes multiple interrupt sources onto the
+ * Nubus slot $C interrupt.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/traps.h>
+#include <asm/bootinfo.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_baboon.h>
+
+/* #define DEBUG_BABOON /**/
+/* #define DEBUG_IRQS /**/
+
+int baboon_present,baboon_active;
+volatile struct baboon *baboon;
+
+void baboon_irq(int, void *, struct pt_regs *);
+
+extern int console_loglevel;
+
+extern int macide_ack_intr(ide_hwif_t *);
+
+/*
+ * Baboon initialization.
+ */
+
+void __init baboon_init(void)
+{
+ if (macintosh_config->ident != MAC_MODEL_PB190) {
+ baboon = NULL;
+ baboon_present = 0;
+ return;
+ }
+
+ baboon = (struct baboon *) BABOON_BASE;
+ baboon_present = 1;
+ baboon_active = 0;
+
+ printk("Baboon detected at %p\n", baboon);
+}
+
+/*
+ * Register the Baboon interrupt dispatcher on nubus slot $C.
+ */
+
+void __init baboon_register_interrupts(void)
+{
+ request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "baboon", (void *) baboon);
+}
+
+/*
+ * Baboon interrupt handler. This works a lot like a VIA.
+ */
+
+void baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int irq_bit,i;
+ unsigned char events;
+
+#ifdef DEBUG_IRQS
+ printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
+ (uint) baboon->mb_control, (uint) baboon->mb_ifr,
+ (uint) baboon->mb_status, baboon_active);
+#endif
+
+ if (!(events = baboon->mb_ifr & 0x07)) return;
+
+ for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
+ if (events & irq_bit/* & baboon_active*/) {
+ baboon_active &= ~irq_bit;
+ mac_do_irq_list(IRQ_BABOON_0 + i, regs);
+ baboon_active |= irq_bit;
+ baboon->mb_ifr &= ~irq_bit;
+ }
+ }
+#if 0
+ if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
+ /* for now we need to smash all interrupts */
+ baboon->mb_ifr &= ~events;
+#endif
+}
+
+void baboon_irq_enable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+#ifdef DEBUG_IRQUSE
+ printk("baboon_irq_enable(%d)\n", irq);
+#endif
+ baboon_active |= (1 << irq_idx);
+}
+
+void baboon_irq_disable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+#ifdef DEBUG_IRQUSE
+ printk("baboon_irq_disable(%d)\n", irq);
+#endif
+ baboon_active &= ~(1 << irq_idx);
+}
+
+void baboon_irq_clear(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ baboon->mb_ifr &= ~(1 << irq_idx);
+}
+
+int baboon_irq_pending(int irq)
+{
+ int irq_idx = IRQ_IDX(irq);
+
+ return baboon->mb_ifr & (1 << irq_idx);
+}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index b5057f6e8..c1154b6aa 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -42,16 +42,6 @@
#include <asm/mac_oss.h>
#include <asm/mac_psc.h>
-/* Offset between Unix time (1970-based) and Mac time (1904-based) */
-
-#define MAC_TIME_OFFSET 2082844800
-
-/*
- * hardware reset vector
- */
-
-static void (*rom_reset)(void);
-
/* Mac bootinfo struct */
struct mac_booter_data mac_bi_data = {0,};
@@ -76,10 +66,11 @@ extern int mackbd_init_hw(void);
extern void mackbd_leds(unsigned int leds);
/* Mac specific timer functions */
+extern void mac_gettod (int *, int *, int *, int *, int *, int *);
extern unsigned long mac_gettimeoffset (void);
-static void mac_gettod (int *, int *, int *, int *, int *, int *);
-static int mac_hwclk (int, struct hwclk_time *);
-static int mac_set_clock_mmss (unsigned long);
+extern int mac_hwclk (int, struct hwclk_time *);
+extern int mac_set_clock_mmss (unsigned long);
+extern int mac_get_irq_list(char *);
extern void iop_preinit(void);
extern void iop_init(void);
extern void via_init(void);
@@ -87,6 +78,7 @@ extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
extern void via_flush_cache(void);
extern void oss_init(void);
extern void psc_init(void);
+extern void baboon_init(void);
extern void (*kd_mksound)(unsigned int, unsigned int);
extern void mac_mksound(unsigned int, unsigned int);
@@ -99,18 +91,6 @@ extern void nubus_sweep_video(void);
extern void mac_debug_init(void);
extern void mac_debugging_long(int, long);
-/* poweroff functions */
-extern void via_poweroff(void);
-extern void oss_poweroff(void);
-extern void adb_poweroff(void);
-extern void adb_hwreset(void);
-
-/* pram functions */
-extern __u32 via_read_time(void);
-extern void via_write_time(__u32);
-extern __u32 adb_read_time(void);
-extern void adb_write_time(__u32);
-
#ifdef CONFIG_MAGIC_SYSRQ
static char mac_sysrq_xlate[128] =
"\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */
@@ -140,186 +120,6 @@ static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
extern int console_loglevel;
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
-/*
- * This function translates seconds since 1970 into a proper date.
- *
- * Algorithm cribbed from glibc2.1, __offtime().
- */
-#define SECS_PER_MINUTE (60)
-#define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-static void unmktime(unsigned long time, long offset,
- int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
- /* How many days come before each month (0-12). */
- static const unsigned short int __mon_yday[2][13] =
- {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
- long int days, rem, y, wday, yday;
- const unsigned short int *ip;
-
- days = time / SECS_PER_DAY;
- rem = time % SECS_PER_DAY;
- rem += offset;
- while (rem < 0) {
- rem += SECS_PER_DAY;
- --days;
- }
- while (rem >= SECS_PER_DAY) {
- rem -= SECS_PER_DAY;
- ++days;
- }
- *hourp = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- *minp = rem / SECS_PER_MINUTE;
- *secp = rem % SECS_PER_MINUTE;
- /* January 1, 1970 was a Thursday. */
- wday = (4 + days) % 7; /* Day in the week. Not currently used */
- if (wday < 0) wday += 7;
- y = 1970;
-
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
-#define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
- while (days < 0 || days >= (__isleap (y) ? 366 : 365))
- {
- /* Guess a corrected year, assuming 365 days per year. */
- long int yg = y + days / 365 - (days % 365 < 0);
-
- /* Adjust DAYS and Y to match the guessed year. */
- days -= ((yg - y) * 365
- + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- y = yg;
- }
- *yearp = y - 1900;
- yday = days; /* day in the year. Not currently used. */
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
- *monp = y;
- *dayp = days + 1; /* day in the month */
- return;
-}
-
-/*
- * Return the boot time for use in initializing the kernel clock.
- *
- * I'd like to read the hardware clock here but many machines read
- * the PRAM through ADB, and interrupts aren't initialized when this
- * is called so ADB obviously won't work.
- */
-
-static void mac_gettod(int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
- /* Yes the GMT bias is backwards. It looks like Penguin is
- screwing up the boottime it gives us... This works for me
- in Canada/Eastern but it might be wrong everywhere else. */
- unmktime(mac_bi_data.boottime, -mac_bi_data.gmtbias * 60,
- yearp, monp, dayp, hourp, minp, secp);
- /* For some reason this is off by one */
- *monp = *monp + 1;
-}
-
-/*
- * Read/write the hardware clock.
- */
-
-static int mac_hwclk(int op, struct hwclk_time *t)
-{
- unsigned long now;
-
- if (!op) { /* read */
- if (macintosh_config->adb_type == MAC_ADB_II) {
- now = via_read_time();
- } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- now = adb_read_time();
- } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
- now = via_read_time();
- } else {
- now = MAC_TIME_OFFSET;
- }
-
- now -= MAC_TIME_OFFSET;
-
- t->wday = 0;
- unmktime(now, 0,
- &t->year, &t->mon, &t->day,
- &t->hour, &t->min, &t->sec);
- } else { /* write */
- now = mktime(t->year + 1900, t->mon + 1, t->day,
- t->hour, t->min, t->sec) + MAC_TIME_OFFSET;
-
- if (macintosh_config->adb_type == MAC_ADB_II) {
- via_write_time(now);
- } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- adb_write_time(now);
- } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
- via_write_time(now);
- }
- }
- return 0;
-}
-
-/*
- * Set minutes/seconds in the hardware clock
- */
-
-static int mac_set_clock_mmss (unsigned long nowtime)
-{
- struct hwclk_time now;
-
- mac_hwclk(0, &now);
- now.sec = nowtime % 60;
- now.min = (nowtime / 60) % 60;
- mac_hwclk(1, &now);
-
- return 0;
-}
-
#if 0
void mac_waitbut (void)
{
@@ -330,9 +130,23 @@ void mac_waitbut (void)
extern struct consw fb_con;
extern struct fb_info *mac_fb_init(long *);
- /*
- * Parse a Macintosh-specific record in the bootinfo
- */
+extern void mac_default_handler(int, void *, struct pt_regs *);
+
+void (*mac_handlers[8])(int, void *, struct pt_regs *)=
+{
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler
+};
+
+/*
+ * Parse a Macintosh-specific record in the bootinfo
+ */
int __init mac_parse_bootinfo(const struct bi_record *record)
{
@@ -384,9 +198,9 @@ int __init mac_parse_bootinfo(const struct bi_record *record)
}
/*
- * Flip into 24bit mode for an instant - flushes the L2 cache card. We
- * have to disable interrupts for this. Our IRQ handlers will crap
- * themselves if they take an IRQ in 24bit mode!
+ * Flip into 24bit mode for an instant - flushes the L2 cache card. We
+ * have to disable interrupts for this. Our IRQ handlers will crap
+ * themselves if they take an IRQ in 24bit mode!
*/
static void mac_cache_card_flush(int writeback)
@@ -414,6 +228,8 @@ void __init config_mac(void)
enable_irq = mac_enable_irq;
disable_irq = mac_disable_irq;
mach_get_model = mac_get_model;
+ mach_default_handler = &mac_handlers;
+ mach_get_irq_list = mac_get_irq_list;
mach_gettimeoffset = mac_gettimeoffset;
mach_gettod = mac_gettod;
mach_hwclk = mac_hwclk;
@@ -489,7 +305,6 @@ struct mac_model *macintosh_config;
static struct mac_model mac_data_table[]=
{
/*
- * The default machine, in case we get an unsupported one
* We'll pretend to be a Macintosh II, that's pretty safe.
*/
@@ -509,10 +324,6 @@ static struct mac_model mac_data_table[]=
* Weirdified MacII hardware - all subtley different. Gee thanks
* Apple. All these boxes seem to have VIA2 in a different place to
* the MacII (+1A000 rather than +4000)
- *
- * The IIfx apparently has different ADB hardware, and stuff
- * so zany nobody knows how to drive it.
- * Even so, with Marten's help we'll try to deal with it :-)
* CSA: see http://developer.apple.com/technotes/hw/hw_09.html
*/
@@ -584,28 +395,33 @@ static struct mac_model mac_data_table[]=
{ MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_MACE, MAC_NUBUS},
/*
- * Power books - seem similar to early Quadras ? (most have 030 though)
+ * The PowerBooks all the same "Combo" custom IC for SCSI and SCC
+ * and a PMU (in two variations?) for ADB. Most of them use the
+ * Quadra-style VIAs. A few models also have IDE from hell.
*/
- { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- /* The PB150 has IDE, and IIci style VIA */
- { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_NONE, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- /* These have onboard SONIC */
- { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB190, "PowerBook 190", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_BABOON, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
/*
- * Power book Duos - similar to Power books, I hope
+ * PowerBook Duos are pretty much like normal PowerBooks
+ * All of these probably have onboard SONIC in the Dock which
+ * means we'll have to probe for it eventually.
+ *
+ * Are these reallly MAC_VIA_IIci? The developer notes for the
+ * Duos show pretty much the same custom parts as in most of
+ * the other PowerBooks which would imply MAC_VIA_QUADRA.
*/
- /* All of these might have onboard SONIC in the Dock but I'm not quite sure */
{ MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
@@ -694,6 +510,7 @@ void mac_identify(void)
via_init();
oss_init();
psc_init();
+ baboon_init();
}
void mac_report_hardware(void)
@@ -706,137 +523,3 @@ static void mac_get_model(char *str)
strcpy(str,"Macintosh ");
strcat(str, macintosh_config->name);
}
-
-/*
- * The power switch - yes it's software!
- */
-
-void mac_poweroff(void)
-{
- /*
- * MAC_ADB_IISI may need to be moved up here if it doesn't actually
- * work using the ADB packet method. --David Kilzer
- */
-
- if (oss_present) {
- oss_poweroff();
- } else if (macintosh_config->adb_type == MAC_ADB_II) {
- via_poweroff();
- } else {
- adb_poweroff();
- }
-}
-
-/*
- * Not all Macs support software power down; for the rest, just
- * try the ROM reset vector ...
- */
-void mac_reset(void)
-{
- /*
- * MAC_ADB_IISI may need to be moved up here if it doesn't actually
- * work using the ADB packet method. --David Kilzer
- */
-
- if (macintosh_config->adb_type == MAC_ADB_II) {
- unsigned long cpu_flags;
-
- /* 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);
-
- if (macintosh_config->ident == MAC_MODEL_SE30) {
- /*
- * MSch: Machines known to crash on ROM reset ...
- */
- printk("System halted.\n");
- while(1);
- } else {
- save_flags(cpu_flags);
- cli();
-
- rom_reset();
-
- restore_flags(cpu_flags);
- }
-
- /* 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 ? */
- while(1); /* Just in case .. */
- } else if (macintosh_config->adb_type == MAC_ADB_IISI
- || macintosh_config->adb_type == MAC_ADB_CUDA) {
- adb_hwreset();
- } else if (CPU_IS_030) {
-
- /* 030-specific reset routine. The idea is general, but the
- * specific registers to reset are '030-specific. Until I
- * have a non-030 machine, I can't test anything else.
- * -- C. Scott Ananian <cananian@alumni.princeton.edu>
- */
-
- unsigned long rombase = 0x40000000;
-
- /* make a 1-to-1 mapping, using the transparent tran. reg. */
- unsigned long virt = (unsigned long) mac_reset;
- unsigned long phys = virt_to_phys(mac_reset);
- unsigned long offset = phys-virt;
- cli(); /* lets not screw this up, ok? */
- __asm__ __volatile__(".chip 68030\n\t"
- "pmove %0,%/tt0\n\t"
- ".chip 68k"
- : : "m" ((phys&0xFF000000)|0x8777));
- /* Now jump to physical address so we can disable MMU */
- __asm__ __volatile__(
- ".chip 68030\n\t"
- "lea %/pc@(1f),%/a0\n\t"
- "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
- "addl %0,%/sp\n\t"
- "pflusha\n\t"
- "jmp %/a0@\n\t" /* jump into physical memory */
- "0:.long 0\n\t" /* a constant zero. */
- /* OK. Now reset everything and jump to reset vector. */
- "1:\n\t"
- "lea %/pc@(0b),%/a0\n\t"
- "pmove %/a0@, %/tc\n\t" /* disable mmu */
- "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
- "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
- "movel #0, %/a0\n\t"
- "movec %/a0, %/vbr\n\t" /* clear vector base register */
- "movec %/a0, %/cacr\n\t" /* disable caches */
- "movel #0x0808,%/a0\n\t"
- "movec %/a0, %/cacr\n\t" /* flush i&d caches */
- "movew #0x2700,%/sr\n\t" /* set up status register */
- "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
- "movec %/a0, %/isp\n\t"
- "movel %1@(0x4),%/a0\n\t" /* load reset vector */
- "reset\n\t" /* reset external devices */
- "jmp %/a0@\n\t" /* jump to the reset vector */
- ".chip 68k"
- : : "r" (offset), "a" (rombase) : "a0");
-
- /* should never get here */
- sti(); /* sure, why not */
- printk ("030 Restart failed. Please restart manually.\n");
- while(1);
- } else {
- /* We never make it here... The above shoule handle all cases. */
- printk ("Restart failed. Please restart manually.\n");
-
- /* XXX - delay do we need to spin here ? */
- while(1); /* Just in case .. */
- }
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 8
- * End:
- */
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 21969ce6f..3163e3ea3 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -319,7 +319,7 @@ void __init iop_register_interrupts(void)
{
if (iop_ism_present) {
if (oss_present) {
- request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+ sys_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
IRQ_FLG_LOCK, "ISM IOP",
(void *) IOP_NUM_ISM);
oss_irq_enable(IRQ_MAC_ADB);
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index a795d82ed..febba1982 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -35,8 +35,8 @@
* 3 - unused (?)
*
* 4 - SCC (slot number determined by reading RR3 on the SSC itself)
- * - slot 0: SCC channel A
- * - slot 1: SCC channel B
+ * - slot 1: SCC channel A
+ * - slot 2: SCC channel B
*
* 5 - unused (?)
* [serial errors or special conditions seem to raise level 6
@@ -55,8 +55,8 @@
* - slot 5: Slot $E
*
* 4 - SCC IOP
- * - slot 0: SCC channel A
- * - slot 1: SCC channel B
+ * - slot 1: SCC channel A
+ * - slot 2: SCC channel B
*
* 5 - ISM IOP (ADB?)
*
@@ -100,19 +100,18 @@
* bits. The handlers for this new machspec interrupt number are then
* called. This puts Nubus interrupts into the range 56-62.
*
+ * - The Baboon interrupts (used on some PowerBooks) are an even more special
+ * case. They're hidden behind the Nubus slot $C interrupt thus adding a
+ * third layer of indirection. Why oh why did the Apple engineers do that?
+ *
* - We support "fast" and "slow" handlers, just like the Amiga port. The
* fast handlers are called first and with all interrupts disabled. They
* are expected to execute quickly (hence the name). The slow handlers are
* called last with interrupts enabled and the interrupt level restored.
* They must therefore be reentrant.
*
- * - Drivers should never try to request autovector interrupt numbers. It
- * won't work.
- *
* TODO:
*
- * o Perhaps build some intelligence into mac_SCC_handler(); we could check
- * the SCC ourselves and only call the handler for the appopriate channel.
*/
#include <linux/types.h>
@@ -125,6 +124,7 @@
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
+#include <asm/bootinfo.h>
#include <asm/machw.h>
#include <asm/macintosh.h>
#include <asm/mac_via.h>
@@ -133,6 +133,18 @@
#include <asm/macints.h>
/*
+ * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
+ * Each node contains one handler to be called whenever the interrupt
+ * occurs, with fast handlers listed before slow handlers.
+ */
+
+irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
+
+/* SCC interrupt mask */
+
+static int scc_mask;
+
+/*
* VIA/RBV hooks
*/
@@ -176,6 +188,26 @@ extern int psc_irq_pending(int);
extern void iop_register_interrupts(void);
/*
+ * Baboon hooks
+ */
+
+extern int baboon_present;
+
+extern void baboon_init(void);
+extern void baboon_register_interrupts(void);
+extern void baboon_irq_enable(int);
+extern void baboon_irq_disable(int);
+extern void baboon_irq_clear(int);
+extern int baboon_irq_pending(int);
+
+/*
+ * SCC interrupt routines
+ */
+
+static void scc_irq_enable(int);
+static void scc_irq_disable(int);
+
+/*
* console_loglevel determines NMI handler function
*/
@@ -184,17 +216,27 @@ extern int console_loglevel;
extern void mac_bang(int, void *, struct pt_regs *);
void mac_nmi_handler(int, void *, struct pt_regs *);
-void mac_SCC_handler(int, void *, struct pt_regs *);
+void mac_debug_handler(int, void *, struct pt_regs *);
/* #define DEBUG_MACINTS */
void mac_init_IRQ(void)
{
+ int i;
+
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Setting things up...\n");
#endif
+ /* Initialize the IRQ handler lists. Initially each list is empty, */
+
+ for (i = 0; i < NUM_MAC_SOURCES; i++) {
+ mac_irq_list[i] = NULL;
+ }
+
+ scc_mask = 0;
+
/*
- * Register the handlers for the the master IRQ handlers
+ * Now register the handlers for the the master IRQ handlers
* at levels 1-7. Most of the work is done elsewhere.
*/
@@ -204,8 +246,9 @@ void mac_init_IRQ(void)
via_register_interrupts();
}
if (psc_present) psc_register_interrupts();
+ if (baboon_present) baboon_register_interrupts();
iop_register_interrupts();
- request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", mac_nmi_handler);
+ sys_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", mac_nmi_handler);
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Done!\n");
#endif
@@ -284,27 +327,20 @@ static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
void mac_do_irq_list(int irq, struct pt_regs *fp)
{
- irq_node_t *node, *slow_nodes, **list = NULL;
+ irq_node_t *node, *slow_nodes;
unsigned long cpu_flags;
kstat.irqs[0][irq]++;
- if (irq < VIA1_SOURCE_BASE) {
- list = &autoirq_list[irq];
- } else if (irq < NUM_MAC_SOURCES) {
- list = &userirq_list[irq - VIA1_SOURCE_BASE];
- }
- if (!list) return;
-
#ifdef DEBUG_SPURIOUS
- if (!*list && (console_loglevel > 7)) {
+ if (!mac_irq_list[irq] && (console_loglevel > 7)) {
printk("mac_do_irq_list: spurious interrupt %d!\n", irq);
return;
}
#endif
/* serve first fast and normal handlers */
- for (node = *list;
+ for (node = mac_irq_list[irq];
node && (!(node->flags & IRQ_FLG_SLOW));
node = node->next)
node->handler(irq, node->dev_id, fp);
@@ -329,7 +365,9 @@ void mac_do_irq_list(int irq, struct pt_regs *fp)
void mac_enable_irq (unsigned int irq)
{
- switch(IRQ_SRC(irq)) {
+ int irq_src = IRQ_SRC(irq);
+
+ switch(irq_src) {
case 1: via_irq_enable(irq);
break;
case 2:
@@ -346,6 +384,12 @@ void mac_enable_irq (unsigned int irq)
psc_irq_enable(irq);
} else if (oss_present) {
oss_irq_enable(irq);
+ } else if (irq_src == 4) {
+ scc_irq_enable(irq);
+ }
+ break;
+ case 8: if (baboon_present) {
+ baboon_irq_enable(irq);
}
break;
}
@@ -353,12 +397,13 @@ void mac_enable_irq (unsigned int irq)
void mac_disable_irq (unsigned int irq)
{
- switch(IRQ_SRC(irq)) {
+ int irq_src = IRQ_SRC(irq);
+
+ switch(irq_src) {
case 1: via_irq_disable(irq);
break;
case 2:
- case 7:
- if (oss_present) {
+ case 7: if (oss_present) {
oss_irq_disable(irq);
} else {
via_irq_disable(irq);
@@ -371,6 +416,12 @@ void mac_disable_irq (unsigned int irq)
psc_irq_disable(irq);
} else if (oss_present) {
oss_irq_disable(irq);
+ } else if (irq_src == 4) {
+ scc_irq_disable(irq);
+ }
+ break;
+ case 8: if (baboon_present) {
+ baboon_irq_disable(irq);
}
break;
}
@@ -397,6 +448,10 @@ void mac_clear_irq( unsigned int irq )
oss_irq_clear(irq);
}
break;
+ case 8: if (baboon_present) {
+ baboon_irq_clear(irq);
+ }
+ break;
}
}
@@ -434,29 +489,37 @@ int mac_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
- int vec, ret;
+ irq_node_t *node;
#ifdef DEBUG_MACINTS
printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname);
#endif
if (irq < VIA1_SOURCE_BASE) {
- vec = VEC_SPUR + irq;
- } else if (irq < NUM_MAC_SOURCES) {
- vec = VEC_USER + irq - VIA1_SOURCE_BASE;
- } else {
+ return sys_request_irq(irq, handler, flags, devname, dev_id);
+ }
+
+ if (irq >= NUM_MAC_SOURCES) {
printk ("%s: unknown irq %d requested by %s\n",
__FUNCTION__, irq, devname);
- return -EAGAIN;
}
- ret = sys_request_listirq(vec, handler, flags, devname, dev_id);
- if (!ret) {
- vectors[vec] = autoirq_listhandler;
- mac_enable_irq(irq);
- }
+ /* Get a node and stick it onto the right list */
+
+ if (!(node = new_irq_node())) return -ENOMEM;
+
+ node->handler = handler;
+ node->flags = flags;
+ node->dev_id = dev_id;
+ node->devname = devname;
+ node->next = NULL;
+ mac_insert_irq(&mac_irq_list[irq], node);
+
+ /* Now enable the IRQ source */
+
+ mac_enable_irq(irq);
- return ret;
+ return 0;
}
/*
@@ -465,30 +528,120 @@ int mac_request_irq(unsigned int irq,
void mac_free_irq(unsigned int irq, void *dev_id)
{
- irq_node_t **list = NULL;
- int vec = 0;
-
#ifdef DEBUG_MACINTS
printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id);
#endif
if (irq < VIA1_SOURCE_BASE) {
- vec = VEC_SPUR + irq;
- list = &autoirq_list[irq];
- } else if (irq < NUM_MAC_SOURCES) {
- vec = VEC_USER + irq - VIA1_SOURCE_BASE;
- list = &userirq_list[irq - VIA1_SOURCE_BASE];
+ return sys_free_irq(irq, dev_id);
+ }
+
+ if (irq >= NUM_MAC_SOURCES) {
+ printk ("%s: unknown irq %d freed\n",
+ __FUNCTION__, irq);
+ return;
}
- if (!list) return;
- sys_free_irq(vec, dev_id);
+ mac_delete_irq(&mac_irq_list[irq], dev_id);
/* If the list for this interrupt is */
/* empty then disable the source. */
- if (!*list) {
+ if (!mac_irq_list[irq]) {
mac_disable_irq(irq);
- vectors[vec] = bad_interrupt;
+ }
+}
+
+/*
+ * Generate a pretty listing for /proc/interrupts
+ *
+ * By the time we're called the autovector interrupt list has already been
+ * generated, so we just need to do the machspec interrupts.
+ *
+ * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers.
+ * Also removed display of num_spurious it is already
+ * displayed for us as autovector irq 0.
+ */
+
+int mac_get_irq_list (char *buf)
+{
+ int i, len = 0;
+ irq_node_t *node;
+ char *base;
+
+ /* Don't do Nubus interrupts in this loop; we do them separately */
+ /* below so that we can print slot numbers instead of IRQ numbers */
+
+ for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) {
+
+ /* Nonexistant interrupt or nothing registered; skip it. */
+
+ if ((node = mac_irq_list[i]) == NULL) continue;
+ if (node->flags & IRQ_FLG_STD) continue;
+
+ base = "";
+ switch(IRQ_SRC(i)) {
+ case 1: base = "via1";
+ break;
+ case 2: if (oss_present) {
+ base = "oss";
+ } else {
+ base = "via2";
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6: if (psc_present) {
+ base = "psc";
+ } else if (oss_present) {
+ base = "oss";
+ } else {
+ if (IRQ_SRC(i) == 4) base = "scc";
+ }
+ break;
+ case 7: base = "nbus";
+ break;
+ case 8: base = "bbn";
+ break;
+ }
+ len += sprintf(buf+len, "%4s %2d: %10u ",
+ base, i, kstat.irqs[0][i]);
+
+ do {
+ if (node->flags & IRQ_FLG_FAST) {
+ len += sprintf(buf+len, "F ");
+ } else if (node->flags & IRQ_FLG_SLOW) {
+ len += sprintf(buf+len, "S ");
+ } else {
+ len += sprintf(buf+len, " ");
+ }
+ len += sprintf(buf+len, "%s\n", node->devname);
+ if ((node = node->next)) {
+ len += sprintf(buf+len, " ");
+ }
+ } while(node);
+
+ }
+ return len;
+}
+
+void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef DEBUG_SPURIOUS
+ if (console_loglevel > 6) {
+ printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
+ }
+#endif
+}
+
+static int num_debug[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (num_debug[irq] < 10) {
+ printk("DEBUG: Unexpected IRQ %d\n", irq);
+ num_debug[irq]++;
}
}
@@ -543,12 +696,53 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
}
/*
- * SCC master interrupt handler; sole purpose: pass the registered
- * async struct to the SCC handler proper.
+ * Simple routines for masking and unmasking
+ * SCC interrupts in cases where this can't be
+ * done in hardware (only the PSC can do that.)
+ */
+
+static void scc_irq_enable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ scc_mask |= (1 << irq_idx);
+}
+
+static void scc_irq_disable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ scc_mask &= ~(1 << irq_idx);
+}
+
+/*
+ * SCC master interrupt handler. We have to do a bit of magic here
+ * to figure out what channel gave us the interrupt; putting this
+ * here is cleaner than hacking it into drivers/char/macserial.c.
*/
-void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs)
+void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs)
{
- mac_do_irq_list(IRQ_SCCA, regs);
- mac_do_irq_list(IRQ_SCCB, regs);
+ volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
+ unsigned char reg;
+ unsigned long cpu_flags;
+
+ /* Read RR3 from the chip. Always do this on channel A */
+ /* This must be an atomic operation so disable irqs. */
+
+ save_flags(cpu_flags); cli();
+ *scc = 3;
+ reg = *scc;
+ restore_flags(cpu_flags);
+
+ /* Now dispatch. Bits 0-2 are for channel B and */
+ /* bits 3-5 are for channel A. We can safely */
+ /* ignore the remaining bits here. */
+ /* */
+ /* Note that we're ignoring scc_mask for now. */
+ /* If we actually mask the ints then we tend to */
+ /* get hammered by very persistant SCC irqs, */
+ /* and since they're autovector interrupts they */
+ /* pretty much kill the system. */
+
+ if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs);
+ if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs);
}
diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c
deleted file mode 100644
index 0d70357dc..000000000
--- a/arch/m68k/mac/mackeyb.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
- * 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
- * for more details.
- */
-
-/*
- * 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>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-/* keyb */
-#include <linux/keyboard.h>
-#include <linux/random.h>
-#include <linux/delay.h>
-/* keyb */
-
-#include <asm/setup.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-
-#include <asm/macintosh.h>
-#include <asm/macints.h>
-/* for keyboard_input stuff */
-#include <asm/adb.h>
-#define KEYB_KEYREG 0 /* register # for key up/down data */
-#define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */
-#define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */
-/* end keyboard_input stuff */
-
-#include <linux/kbd_kern.h>
-#include <linux/kbd_ll.h>
-
-static void kbd_repeat(unsigned long);
-static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
-static int last_keycode;
-
-static void input_keycode(int, int);
-
-extern struct kbd_struct kbd_table[];
-
-extern void adb_bus_init(void);
-extern void handle_scancode(unsigned char, int);
-extern void put_queue(int);
-
-/* keyb */
-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 *);
-
-#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 */
-
-/* this map indicates which keys shouldn't autorepeat. */
-static unsigned char dont_repeat[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/*
- * Mac private key maps
- */
-u_short mac_plain_map[NR_KEYS] __initdata = {
- 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78,
- 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72,
- 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035,
- 0xf03d, 0xf039, 0xf037, 0xf02d, 0xf038, 0xf030, 0xf05d, 0xfb6f,
- 0xfb75, 0xf05b, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf027,
- 0xfb6b, 0xf03b, 0xf05c, 0xf02c, 0xf02f, 0xfb6e, 0xfb6d, 0xf02e,
- 0xf009, 0xf020, 0xf060, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xfb61, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf109, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117,
- 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_shift_map[NR_KEYS] __initdata = {
- 0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb48, 0xfb47, 0xfb5a, 0xfb58,
- 0xfb43, 0xfb56, 0xf200, 0xfb42, 0xfb51, 0xfb57, 0xfb45, 0xfb52,
- 0xfb59, 0xfb54, 0xf021, 0xf040, 0xf023, 0xf024, 0xf05e, 0xf025,
- 0xf02b, 0xf028, 0xf026, 0xf05f, 0xf02a, 0xf029, 0xf07d, 0xfb4f,
- 0xfb55, 0xf07b, 0xfb49, 0xfb50, 0xf201, 0xfb4c, 0xfb4a, 0xf022,
- 0xfb4b, 0xf03a, 0xf07c, 0xf03c, 0xf03f, 0xfb4e, 0xfb4d, 0xf03e,
- 0xf009, 0xf020, 0xf07e, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xfb41, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf10e, 0xf10f, 0xf110, 0xf10c, 0xf111, 0xf112, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf203, 0xf200, 0xf113, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf20b, 0xf116, 0xf10d, 0xf117,
- 0xf10b, 0xf20a, 0xf10a, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_altgr_map[NR_KEYS] __initdata = {
- 0xf914, 0xfb73, 0xf917, 0xf919, 0xfb68, 0xfb67, 0xfb7a, 0xfb78,
- 0xf916, 0xfb76, 0xf200, 0xf915, 0xfb71, 0xfb77, 0xf918, 0xfb72,
- 0xfb79, 0xfb74, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
- 0xf200, 0xf05d, 0xf07b, 0xf05c, 0xf05b, 0xf07d, 0xf07e, 0xfb6f,
- 0xfb75, 0xf200, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf200,
- 0xfb6b, 0xf200, 0xf200, 0xf200, 0xf200, 0xfb6e, 0xfb6d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf90a, 0xf90b, 0xf90c, 0xf90d, 0xf90e, 0xf90f,
- 0xf910, 0xf911, 0xf914, 0xf912, 0xf913, 0xf200, 0xf200, 0xf200,
- 0xf510, 0xf511, 0xf512, 0xf50e, 0xf513, 0xf514, 0xf200, 0xf516,
- 0xf200, 0xf10c, 0xf200, 0xf202, 0xf200, 0xf515, 0xf200, 0xf517,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf50f, 0xf117,
- 0xf50d, 0xf119, 0xf50c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_ctrl_map[NR_KEYS] __initdata = {
- 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018,
- 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012,
- 0xf019, 0xf014, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01e, 0xf01d,
- 0xf200, 0xf200, 0xf01f, 0xf01f, 0xf07f, 0xf200, 0xf01d, 0xf00f,
- 0xf015, 0xf01b, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf007,
- 0xf00b, 0xf200, 0xf01c, 0xf200, 0xf07f, 0xf00e, 0xf00d, 0xf20e,
- 0xf200, 0xf000, 0xf000, 0xf008, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf204, 0xf200, 0xf109, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117,
- 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_shift_ctrl_map[NR_KEYS] __initdata = {
- 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018,
- 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012,
- 0xf019, 0xf014, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, 0xf00f,
- 0xf015, 0xf200, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf200,
- 0xf00b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf00e, 0xf00d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf200, 0xf117,
- 0xf200, 0xf119, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf20c,
-};
-
-u_short mac_alt_map[NR_KEYS] __initdata = {
- 0xf861, 0xf873, 0xf864, 0xf866, 0xf868, 0xf867, 0xf87a, 0xf878,
- 0xf863, 0xf876, 0xf200, 0xf862, 0xf871, 0xf877, 0xf865, 0xf872,
- 0xf879, 0xf874, 0xf831, 0xf832, 0xf833, 0xf834, 0xf836, 0xf835,
- 0xf83d, 0xf839, 0xf837, 0xf82d, 0xf838, 0xf830, 0xf85d, 0xf86f,
- 0xf875, 0xf85b, 0xf869, 0xf870, 0xf80d, 0xf86c, 0xf86a, 0xf827,
- 0xf86b, 0xf83b, 0xf85c, 0xf82c, 0xf82f, 0xf86e, 0xf86d, 0xf82e,
- 0xf809, 0xf820, 0xf860, 0xf87f, 0xf200, 0xf81b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf210, 0xf211, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf900, 0xf901, 0xf902, 0xf903, 0xf904, 0xf905,
- 0xf906, 0xf907, 0xf861, 0xf908, 0xf909, 0xf200, 0xf200, 0xf200,
- 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a,
- 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf509, 0xf200, 0xf50b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117,
- 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_ctrl_alt_map[NR_KEYS] __initdata = {
- 0xf801, 0xf813, 0xf804, 0xf806, 0xf808, 0xf807, 0xf81a, 0xf818,
- 0xf803, 0xf816, 0xf200, 0xf802, 0xf811, 0xf817, 0xf805, 0xf812,
- 0xf819, 0xf814, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80f,
- 0xf815, 0xf200, 0xf809, 0xf810, 0xf201, 0xf80c, 0xf80a, 0xf200,
- 0xf80b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80e, 0xf80d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf801, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a,
- 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf509, 0xf200, 0xf50b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117,
- 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-extern unsigned int keymap_count;
-
-/*
- * Misc. defines for testing
- */
-
-extern int console_loglevel;
-
-static struct adb_request led_request;
-extern int in_keybinit;
-
-/*
- * machdep keyboard routines, interface and key repeat method modeled after
- * drivers/macintosh/keyb_mac.c
- */
-
-int mac_kbd_translate(unsigned char keycode, unsigned char *keycodep,
- char raw_mode)
-{
- if (!raw_mode) {
- /*
- * Convert R-shift/control/option to L version.
- * Remap keycode 0 (A) to the unused keycode 0x5a.
- * Other parts of the system assume 0 is not a valid keycode.
- */
- switch (keycode) {
- case 0x7b: keycode = 0x38; break; /* R-shift */
- case 0x7c: keycode = 0x3a; break; /* R-option */
- case 0x7d: keycode = 0x36; break; /* R-control */
- case 0: keycode = 0x5a; break; /* A */
- }
- }
- *keycodep = keycode;
- return 1;
-}
-
-int mac_kbd_unexpected_up(unsigned char keycode)
-{
- return 0x80;
-}
-
-static void
-keyboard_input(unsigned char *data, int nb, struct pt_regs *regs)
-{
- /* first check this is from register 0 */
- if (nb != 5 || (data[2] & 3) != KEYB_KEYREG)
- return; /* ignore it */
- kbd_pt_regs = regs;
- input_keycode(data[3], 0);
- if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f)))
- input_keycode(data[4], 0);
-}
-
-static void
-input_keycode(int keycode, int repeat)
-{
- struct kbd_struct *kbd;
- int up_flag;
-
- 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.
- * Really messy; might need to check if keyboard is in
- * VC_RAW mode for X?.
- * Might also want to know how many buttons need to be emulated.
- * -> hide this as function in arch/m68k/mac ?
- * Current emulation buttons: right alt/option and control
- * (wanted: command and alt/option, or KP= and KP( ...)
- * Debug version; might be rewritten to be faster on normal keys.
- */
- 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 */
- static unsigned char data[4] = { 0, 0x80, 0x80, 0x80 };
-
- button = 0;
- fake_event = 0;
- 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)
- printk("fake event: button2 %d button3 %d button %d\n",
- button2state, button3state, button);
-#endif
- if (button) { /* there's been a button state change */
- /* fake a mouse packet : send all bytes, change one! */
- data[button] = (up_flag ? 0x80 : 0);
- if (adb_mouse_interrupt_hook)
- adb_mouse_interrupt_hook(data, 4);
-#ifdef DEBUG_ADBMOUSE
- else
- printk("mouse_fake: data %2x %2x %2x buttons %2x \n",
- data[1], data[2], data[3],
- ~( (data[1] & 0x80 ? 0 : 4)
- | (data[2] & 0x80 ? 0 : 1)
- | (data[3] & 0x80 ? 0 : 2) )&7 );
-#endif
- }
- /*
- * for mouse 3-button emulation: don't process 'fake' keys!
- * Keys might autorepeat, and console state gets generally messed
- * up enough so that selection stops working.
- */
- if (fake_event)
- return;
- }
-#endif /* CONFIG_ADBMOUSE */
-
- /*
- * Convert R-shift/control/option to L version.
- */
- switch (keycode) {
- case 0x7b: keycode = 0x38; break; /* R-shift */
- case 0x7c: keycode = 0x3a; break; /* R-option */
- case 0x7d: keycode = 0x36; break; /* R-control */
- case 0x0: if (kbd->kbdmode != VC_RAW)
- keycode = 0x5a; /* A; keycode 0 deprecated */
- break;
- }
-
- if (kbd->kbdmode != VC_RAW) {
- if (!up_flag && !dont_repeat[keycode]) {
- last_keycode = keycode;
- repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2);
- add_timer(&repeat_timer);
- }
-
- /*
- * XXX fix caps-lock behaviour by turning the key-up
- * 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!)
- */
- switch (keycode) {
- case 0x39:
- handle_scancode(keycode, 1); /* down */
- up_flag = 0x80; /* see below ... */
- mark_bh(KEYBOARD_BH);
- break;
- case 0x47:
- mark_bh(KEYBOARD_BH);
- break;
- }
- }
-
- handle_scancode(keycode, !up_flag);
-}
-
-static void
-kbd_repeat(unsigned long xxx)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- input_keycode(last_keycode, 1);
- restore_flags(flags);
-}
-
- /* [ACA:23-Mar-97] Three button mouse support. This is designed to
- function with MkLinux DR-2.1 style X servers. It only works with
- three-button mice that conform to Apple's multi-button mouse
- protocol. */
-
- /*
- The X server for MkLinux DR2.1 uses the following unused keycodes to
- read the mouse:
-
- 0x7e This indicates that the next two keycodes should be interpreted
- as mouse information. The first following byte's high bit
- represents the state of the left button. The lower seven bits
- represent the x-axis acceleration. The lower seven bits of the
- second byte represent y-axis acceleration.
-
- 0x3f The x server interprets this keycode as a middle button
- release.
-
- 0xbf The x server interprets this keycode as a middle button
- depress.
-
- 0x40 The x server interprets this keycode as a right button
- release.
-
- 0xc0 The x server interprets this keycode as a right button
- depress.
-
- NOTES: There should be a better way of handling mice in the X server.
- The MOUSE_ESCAPE code (0x7e) should be followed by three bytes instead
- of two. The three mouse buttons should then, in the X server, be read
- as the high-bits of all three bytes. The x and y motions can still be
- in the first two bytes. Maybe I'll do this...
- */
-
- /*
- Handler 4 -- Apple Extended mouse protocol.
-
- For Apple's 3-button mouse protocol the data array will contain the
- following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = 0100 0000 Extended protocol register.
- Bits 6-7 are the device id, which should be 1.
- Bits 4-5 are resolution which is in "units/inch".
- The Logitech MouseMan returns these bits clear but it has
- 200/300cpi resolution.
- Bits 0-3 are unique vendor id.
- data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
- Bits 2-3 should be 8 + 4.
- Bits 4-7 should be 3 for a mouse device.
- data[3] = bxxx xxxx Left button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
- data[5] = byyy bxxx Third button and fourth button. Y is additional
- high bits of y-axis motion. XY is additional
- high bits of x-axis motion.
-
- NOTE: data[0] and data[2] are confirmed by the parent function and
- need not be checked here.
- */
-
- /*
- Handler 1 -- 100cpi original Apple mouse protocol.
- Handler 2 -- 200cpi original Apple mouse protocol.
-
- For Apple's standard one-button mouse protocol the data array will
- contain the following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = ???? ???? (?)
- data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
- data[3] = bxxx xxxx First button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
-
- NOTE: data[0] is confirmed by the parent function and need not be
- checked here.
- */
-
-static void
-mouse_input(unsigned char *data, int nb, struct pt_regs *regs)
-{
- struct kbd_struct *kbd;
- int i;
-
- if (nb < 5 || nb > 6 || (data[2] & 3) != MOUSE_DATAREG) {
- printk("data from mouse:");
- for (i = 0; i < nb; ++i)
- printk(" %x", data[i]);
- printk("\n");
- return;
- }
-
- if (adb_mouse_interrupt_hook) {
- adb_mouse_interrupt_hook(data+2, nb-2);
- /*
- * passing the mouse data to i.e. the X server as done for
- * Xpmac will confuse applications on a sane X server :-)
- */
- return;
- }
-#ifdef DEBUG_ADBMOUSE
- else
- if (console_loglevel >= 8)
- printk("mouse_input: data %x %x %x buttons %x dx %d dy %d \n",
- data[3], data[4], data[5],
- ~((data[3] & 0x80 ? 0 : 4)
- | (data[4] & 0x80 ? 0 : 1)
- | (data[5] & 0x80 ? 0 : 2))&7,
- ((data[4]&0x7f) < 64 ? (data[4]&0x7f) : (data[4]&0x7f)-128 ),
- ((data[3]&0x7f) < 64 ? -(data[3]&0x7f) : 128-(data[3]&0x7f) ) );
-#endif
-
-
- kbd = kbd_table + fg_console;
-
-#if 0 /* The entirely insane way of MkLinux handling mouse input */
- /* Requires put_queue which is static in keyboard.c :-( */
- /* Only send mouse codes when keyboard is in raw mode. */
- if (kbd->kbdmode == VC_RAW) {
- static unsigned char uch_ButtonStateSecond = 0;
- unsigned char uchButtonSecond;
-
- /* Send first button, second button and movement. */
- put_queue( 0x7e );
- put_queue( data[3] );
- put_queue( data[4] );
-
- /* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */
-
- /* Store the button state. */
- uchButtonSecond = (data[4] & 0x80);
-
- /* Send second button. */
- if (uchButtonSecond != uch_ButtonStateSecond) {
- put_queue( 0x3f | uchButtonSecond );
- uch_ButtonStateSecond = uchButtonSecond;
- }
-
- /* Macintosh 3-button mouse (handler 4). */
- if ((nb == 6) && (data[1] & 0x40)) {
- static unsigned char uch_ButtonStateThird = 0;
- unsigned char uchButtonThird;
-
- /* Store the button state for speed. */
- uchButtonThird = (data[5] & 0x80);
-
- /* Send third button. */
- if (uchButtonThird != uch_ButtonStateThird) {
- put_queue( 0x40 | uchButtonThird );
- uch_ButtonStateThird = uchButtonThird;
- }
- }
- }
-#endif /* insane MkLinux mouse hack */
-}
-
-/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
-static unsigned char mac_ledmap[8] = {
- 0, /* none */
- 4, /* scroll lock */
- 1, /* num lock */
- 5, /* scroll + num lock */
- 2, /* caps lock */
- 6, /* caps + scroll lock */
- 3, /* caps + num lock */
- 7, /* caps + num + scroll lock */
-};
-
-static int leds_pending;
-
-void mac_kbd_leds(unsigned int leds)
-{
- if (led_request.got_reply) {
-#ifdef DEBUG_ADB
- if (console_loglevel == 10)
- printk("mac_kbd_leds: got reply, sending request!\n");
-#endif
- adb_request(&led_request, mac_leds_done, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG),
- 0xff, ~mac_ledmap[leds]);
- } else
- leds_pending = leds | 0x100;
-}
-
-static void mac_leds_done(struct adb_request *req)
-{
- int leds;
-
- if (leds_pending) {
- leds = leds_pending & 0xff;
- leds_pending = 0;
- mac_kbd_leds(leds);
- }
- mark_bh(KEYBOARD_BH);
-}
-
-int mac_kbdrate(struct kbd_repeat *k)
-{
- return 0;
-}
-
-int __init mac_keyb_init(void)
-{
- static struct adb_request autopoll_req, confcod_req, mouse_req, readkey_req;
- volatile int ct;
-
- /* setup key map */
- memcpy(key_maps[0], mac_plain_map, sizeof(plain_map));
- memcpy(key_maps[1], mac_shift_map, sizeof(plain_map));
- memcpy(key_maps[2], mac_altgr_map, sizeof(plain_map));
- memcpy(key_maps[4], mac_ctrl_map, sizeof(plain_map));
- memcpy(key_maps[5], mac_shift_ctrl_map, sizeof(plain_map));
- memcpy(key_maps[8], mac_alt_map, sizeof(plain_map));
- memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map));
-
- /* initialize mouse interrupt hook */
- adb_mouse_interrupt_hook = NULL;
-
- /*
- * Might put that someplace else, possibly ....
- */
- adb_bus_init();
-
- /* the input functions ... */
- adb_register(ADB_KEYBOARD, keyboard_input);
- adb_register(ADB_MOUSE, mouse_input);
-
- /* turn on ADB auto-polling in the CUDA */
-
- /*
- * Older boxes don't support CUDA_* targets and CUDA commands
- * instead we emulate them in the adb_request hook to make
- * the code interfaces saner.
- *
- * Note XXX: the Linux PMac and this code both assume the
- * devices are at their primary ids and do not do device
- * assignment. This isn't ideal. We should fix it to follow
- * the reassignment specs.
- */
-
- if (macintosh_config->adb_type == MAC_ADB_CUDA) {
- printk("CUDA autopoll on ...\n");
- adb_request(&autopoll_req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
- ct=0;
- while (!autopoll_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("Keyboard timed out.\n");
- autopoll_req.got_reply = 1;
- }
- }
-
- /*
- * XXX: all ADB requests now in CUDA format; adb_request takes
- * care of that for other Macs.
- */
-
- printk("Configuring keyboard:\n");
-
- udelay(3000);
-
- /*
- * turn on all leds - the keyboard driver will turn them back off
- * via mac_kbd_leds if everything works ok!
- */
- printk("leds on ...\n");
- adb_request(&led_request, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, ~7);
-
- /*
- * The polling stuff should go away as soon as the ADB driver is stable
- */
- ct = 0;
- while (!led_request.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("keyboard timed out.\n");
- led_request.got_reply = 1;
- }
-
-#if 1
- printk("configuring coding mode ...\n");
-
- udelay(3000);
-
- /*
- * get the keyboard to send separate codes for
- * left and right shift, control, option keys.
- */
- adb_request(&confcod_req, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
-
- ct=0;
- while (!confcod_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("keyboard timed out.\n");
- confcod_req.got_reply = 1;
- }
-#endif
-
-#if 0 /* seems to hurt, at least Geert's Mac */
- printk("Configuring mouse (3-button mode) ...\n");
-
- udelay(3000);
-
- /*
- * XXX: taken from the PPC driver again ...
- * Try to switch the mouse (id 3) to handler 4, for three-button
- * mode. (0x20 is Service Request Enable, 0x03 is Device ID).
- */
- adb_request(&mouse_req, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
-
- ct=0;
- while (!mouse_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000)
- printk("Mouse timed out.\n");
-#endif
-
-#if 0
- printk("Start polling keyboard ...\n");
-
- /*
- * get the keyboard to send data back, via the adb_input hook
- * XXX: was never used properly, and the driver takes care
- * of polling and timeout retransmits now.
- * Might be of use if we want to start talking to a specific
- * device here...
- */
- adb_request(&readkey_req, NULL, 2, ADB_PACKET,
- ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG));
-#endif
-
- in_keybinit = 0;
- printk("keyboard init done\n");
-
- return 0;
-}
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
new file mode 100644
index 000000000..a14f25c56
--- /dev/null
+++ b/arch/m68k/mac/misc.c
@@ -0,0 +1,689 @@
+/*
+ * Miscellaneous Mac68K-specific stuff
+ */
+
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/kd.h>
+#include <linux/mm.h>
+
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/setup.h>
+#include <asm/macintosh.h>
+#include <asm/mac_via.h>
+#include <asm/mac_oss.h>
+
+#define BOOTINFO_COMPAT_1_0
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+
+/* Offset between Unix time (1970-based) and Mac time (1904-based) */
+
+#define RTC_OFFSET 2082844800
+
+extern struct mac_booter_data mac_bi_data;
+static void (*rom_reset)(void);
+
+/*
+ * Return the current time as the number of seconds since January 1, 1904.
+ */
+
+static long adb_read_time(void)
+{
+ volatile struct adb_request req;
+ long time;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_GET_TIME);
+
+ time = (req.reply[3] << 24) | (req.reply[4] << 16)
+ | (req.reply[5] << 8) | req.reply[6];
+ return time - RTC_OFFSET;
+}
+
+/*
+ * Set the current system time
+ */
+
+static void adb_write_time(long data)
+{
+ volatile struct adb_request req;
+
+ data += RTC_OFFSET;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 6, CUDA_PACKET, CUDA_SET_TIME,
+ (data >> 24) & 0xFF, (data >> 16) & 0xFF,
+ (data >> 8) & 0xFF, data & 0xFF);
+}
+
+/*
+ * Get a byte from the NVRAM
+ */
+
+static __u8 adb_read_pram(int offset)
+{
+ volatile struct adb_request req;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 4, CUDA_PACKET, CUDA_GET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF);
+ return req.reply[3];
+}
+
+/*
+ * Write a byte to the NVRAM
+ */
+
+static void adb_write_pram(int offset, __u8 data)
+{
+ volatile struct adb_request req;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 5, CUDA_PACKET, CUDA_SET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF,
+ data);
+}
+
+/*
+ * VIA PRAM/RTC access routines
+ *
+ * Must be called with interrupts disabled and
+ * the RTC should be enabled.
+ */
+
+static __u8 via_pram_readbyte(void)
+{
+ int i,reg;
+ __u8 data;
+
+ reg = via1[vBufB] & ~VIA1B_vRTCClk;
+
+ /* Set the RTC data line to be an input. */
+
+ via1[vDirB] &= ~VIA1B_vRTCData;
+
+ /* The bits of the byte come out in MSB order */
+
+ data = 0;
+ for (i = 0 ; i < 8 ; i++) {
+ via1[vBufB] = reg;
+ via1[vBufB] = reg | VIA1B_vRTCClk;
+ data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
+ }
+
+ /* Return RTC data line to output state */
+
+ via1[vDirB] |= VIA1B_vRTCData;
+
+ return data;
+}
+
+static void via_pram_writebyte(__u8 data)
+{
+ int i,reg,bit;
+
+ reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
+
+ /* The bits of the byte go in in MSB order */
+
+ for (i = 0 ; i < 8 ; i++) {
+ bit = data & 0x80? 1 : 0;
+ data <<= 1;
+ via1[vBufB] = reg | bit;
+ via1[vBufB] = reg | bit | VIA1B_vRTCClk;
+ }
+}
+
+/*
+ * Execute a VIA PRAM/RTC command. For read commands
+ * data should point to a one-byte buffer for the
+ * resulting data. For write commands it should point
+ * to the data byte to for the command.
+ *
+ * This function disables all interrupts while running.
+ */
+
+static void via_pram_command(int command, __u8 *data)
+{
+ unsigned long cpu_flags;
+ int is_read;
+
+ save_flags(cpu_flags);
+ cli();
+
+ /* Enable the RTC and make sure the strobe line is high */
+
+ via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
+
+ if (command & 0xFF00) { /* extended (two-byte) command */
+ via_pram_writebyte((command & 0xFF00) >> 8);
+ via_pram_writebyte(command & 0xFF);
+ is_read = command & 0x8000;
+ } else { /* one-byte command */
+ via_pram_writebyte(command);
+ is_read = command & 0x80;
+ }
+ if (is_read) {
+ *data = via_pram_readbyte();
+ } else {
+ via_pram_writebyte(*data);
+ }
+
+ /* All done, disable the RTC */
+
+ via1[vBufB] |= VIA1B_vRTCEnb;
+
+ restore_flags(cpu_flags);
+}
+
+static __u8 via_read_pram(int offset)
+{
+ return 0;
+}
+
+static void via_write_pram(int offset, __u8 data)
+{
+}
+
+/*
+ * Return the current time in seconds since January 1, 1904.
+ *
+ * This only works on machines with the VIA-based PRAM/RTC, which
+ * is basically any machine with Mac II-style ADB.
+ */
+
+static long via_read_time(void)
+{
+ union {
+ __u8 cdata[4];
+ long idata;
+ } result, last_result;
+ int ct;
+
+ /*
+ * The NetBSD guys say to loop until you get the same reading
+ * twice in a row.
+ */
+
+ ct = 0;
+ do {
+ if (++ct > 10) {
+ printk("via_read_time: couldn't get valid time, "
+ "last read = 0x%08X and 0x%08X\n", last_result.idata,
+ result.idata);
+ break;
+ }
+
+ last_result.idata = result.idata;
+ result.idata = 0;
+
+ via_pram_command(0x81, &result.cdata[3]);
+ via_pram_command(0x85, &result.cdata[2]);
+ via_pram_command(0x89, &result.cdata[1]);
+ via_pram_command(0x8D, &result.cdata[0]);
+ } while (result.idata != last_result.idata);
+
+ return result.idata - RTC_OFFSET;
+}
+
+/*
+ * Set the current time to a number of seconds since January 1, 1904.
+ *
+ * This only works on machines with the VIA-based PRAM/RTC, which
+ * is basically any machine with Mac II-style ADB.
+ */
+
+static void via_write_time(long time)
+{
+ union {
+ __u8 cdata[4];
+ long idata;
+ } data;
+ __u8 temp;
+
+ /* Clear the write protect bit */
+
+ temp = 0x55;
+ via_pram_command(0x35, &temp);
+
+ data.idata = time + RTC_OFFSET;
+ via_pram_command(0x01, &data.cdata[3]);
+ via_pram_command(0x05, &data.cdata[2]);
+ via_pram_command(0x09, &data.cdata[1]);
+ via_pram_command(0x0D, &data.cdata[0]);
+
+ /* Set the write protect bit */
+
+ temp = 0xD5;
+ via_pram_command(0x35, &temp);
+}
+
+static void via_shutdown(void)
+{
+ if (rbv_present) {
+ via2[rBufB] &= ~0x04;
+ } else {
+ /* Direction of vDirB is output */
+ via2[vDirB] |= 0x04;
+ /* Send a value of 0 on that line */
+ via2[vBufB] &= ~0x04;
+ mdelay(1000);
+ }
+}
+
+/*
+ * FIXME: not sure how this is supposed to work exactly...
+ */
+
+static void oss_shutdown(void)
+{
+ oss->rom_ctrl = OSS_POWEROFF;
+}
+
+#ifdef CONFIG_ADB_CUDA
+
+static void cuda_restart(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
+}
+
+static void cuda_shutdown(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_POWERDOWN);
+}
+
+#endif /* CONFIG_ADB_CUDA */
+
+#ifdef CONFIG_ADB_PMU
+
+void pmu_restart(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 3, PMU_PACKET, PMU_SET_INTR_MASK,
+ PMU_INT_ADB|PMU_INT_TICK);
+
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, PMU_PACKET, PMU_RESET);
+}
+
+void pmu_shutdown(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 3, PMU_PACKET, PMU_SET_INTR_MASK,
+ PMU_INT_ADB|PMU_INT_TICK);
+
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 6, PMU_PACKET, PMU_SHUTDOWN,
+ 'M', 'A', 'T', 'T');
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+/*
+ *-------------------------------------------------------------------
+ * Below this point are the generic routines; they'll dispatch to the
+ * correct routine for the hardware on which we're running.
+ *-------------------------------------------------------------------
+ */
+
+void mac_pram_read(int offset, __u8 *buffer, int len)
+{
+ __u8 (*func)(int) = NULL;
+ int i;
+
+ if (macintosh_config->adb_type == MAC_ADB_IISI ||
+ macintosh_config->adb_type == MAC_ADB_PB1 ||
+ macintosh_config->adb_type == MAC_ADB_PB2 ||
+ macintosh_config->adb_type == MAC_ADB_CUDA) {
+ func = adb_read_pram;
+ } else {
+ func = via_read_pram;
+ }
+ for (i = 0 ; i < len ; i++) {
+ buffer[i] = (*func)(offset++);
+ }
+}
+
+void mac_pram_write(int offset, __u8 *buffer, int len)
+{
+ void (*func)(int, __u8) = NULL;
+ int i;
+
+ if (macintosh_config->adb_type == MAC_ADB_IISI ||
+ macintosh_config->adb_type == MAC_ADB_PB1 ||
+ macintosh_config->adb_type == MAC_ADB_PB2 ||
+ macintosh_config->adb_type == MAC_ADB_CUDA) {
+ func = adb_write_pram;
+ } else {
+ func = via_write_pram;
+ }
+ for (i = 0 ; i < len ; i++) {
+ (*func)(offset++, buffer[i]);
+ }
+}
+
+void mac_poweroff(void)
+{
+ /*
+ * MAC_ADB_IISI may need to be moved up here if it doesn't actually
+ * work using the ADB packet method. --David Kilzer
+ */
+
+ if (oss_present) {
+ oss_shutdown();
+ } else if (macintosh_config->adb_type == MAC_ADB_II) {
+ via_shutdown();
+#ifdef CONFIG_ADB_CUDA
+ } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
+ cuda_shutdown();
+#endif
+#ifdef CONFIG_ADB_PMU
+ } else if (macintosh_config->adb_type == MAC_ADB_PB1
+ || macintosh_config->adb_type == MAC_ADB_PB2) {
+ pmu_shutdown();
+#endif
+ }
+ sti();
+ printk("It is now safe to turn off your Macintosh.\n");
+ while(1);
+}
+
+void mac_reset(void)
+{
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ unsigned long cpu_flags;
+
+ /* 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);
+
+ if (macintosh_config->ident == MAC_MODEL_SE30) {
+ /*
+ * MSch: Machines known to crash on ROM reset ...
+ */
+ } else {
+ save_flags(cpu_flags);
+ cli();
+
+ rom_reset();
+
+ restore_flags(cpu_flags);
+ }
+#ifdef CONFIG_ADB_CUDA
+ } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
+ cuda_restart();
+#endif
+#ifdef CONFIG_ADB_PMU
+ } else if (macintosh_config->adb_type == MAC_ADB_PB1
+ || macintosh_config->adb_type == MAC_ADB_PB2) {
+ pmu_restart();
+#endif
+ } else if (CPU_IS_030) {
+
+ /* 030-specific reset routine. The idea is general, but the
+ * specific registers to reset are '030-specific. Until I
+ * have a non-030 machine, I can't test anything else.
+ * -- C. Scott Ananian <cananian@alumni.princeton.edu>
+ */
+
+ unsigned long rombase = 0x40000000;
+
+ /* make a 1-to-1 mapping, using the transparent tran. reg. */
+ unsigned long virt = (unsigned long) mac_reset;
+ unsigned long phys = virt_to_phys(mac_reset);
+ unsigned long offset = phys-virt;
+ cli(); /* lets not screw this up, ok? */
+ __asm__ __volatile__(".chip 68030\n\t"
+ "pmove %0,%/tt0\n\t"
+ ".chip 68k"
+ : : "m" ((phys&0xFF000000)|0x8777));
+ /* Now jump to physical address so we can disable MMU */
+ __asm__ __volatile__(
+ ".chip 68030\n\t"
+ "lea %/pc@(1f),%/a0\n\t"
+ "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
+ "addl %0,%/sp\n\t"
+ "pflusha\n\t"
+ "jmp %/a0@\n\t" /* jump into physical memory */
+ "0:.long 0\n\t" /* a constant zero. */
+ /* OK. Now reset everything and jump to reset vector. */
+ "1:\n\t"
+ "lea %/pc@(0b),%/a0\n\t"
+ "pmove %/a0@, %/tc\n\t" /* disable mmu */
+ "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
+ "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
+ "movel #0, %/a0\n\t"
+ "movec %/a0, %/vbr\n\t" /* clear vector base register */
+ "movec %/a0, %/cacr\n\t" /* disable caches */
+ "movel #0x0808,%/a0\n\t"
+ "movec %/a0, %/cacr\n\t" /* flush i&d caches */
+ "movew #0x2700,%/sr\n\t" /* set up status register */
+ "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
+ "movec %/a0, %/isp\n\t"
+ "movel %1@(0x4),%/a0\n\t" /* load reset vector */
+ "reset\n\t" /* reset external devices */
+ "jmp %/a0@\n\t" /* jump to the reset vector */
+ ".chip 68k"
+ : : "r" (offset), "a" (rombase) : "a0");
+ }
+
+ /* should never get here */
+ sti();
+ printk ("Restart failed. Please restart manually.\n");
+ while(1);
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static unsigned long mktime(unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec)
+{
+ if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
+ }
+ return (((
+ (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+ year*365 - 719499
+ )*24 + hour /* now have hours */
+ )*60 + min /* now have minutes */
+ )*60 + sec; /* finally seconds */
+}
+
+/*
+ * This function translates seconds since 1970 into a proper date.
+ *
+ * Algorithm cribbed from glibc2.1, __offtime().
+ */
+#define SECS_PER_MINUTE (60)
+#define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+
+static void unmktime(unsigned long time, long offset,
+ int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ /* How many days come before each month (0-12). */
+ static const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+ long int days, rem, y, wday, yday;
+ const unsigned short int *ip;
+
+ days = time / SECS_PER_DAY;
+ rem = time % SECS_PER_DAY;
+ rem += offset;
+ while (rem < 0) {
+ rem += SECS_PER_DAY;
+ --days;
+ }
+ while (rem >= SECS_PER_DAY) {
+ rem -= SECS_PER_DAY;
+ ++days;
+ }
+ *hourp = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ *minp = rem / SECS_PER_MINUTE;
+ *secp = rem % SECS_PER_MINUTE;
+ /* January 1, 1970 was a Thursday. */
+ wday = (4 + days) % 7; /* Day in the week. Not currently used */
+ if (wday < 0) wday += 7;
+ y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+#define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+ {
+ /* Guess a corrected year, assuming 365 days per year. */
+ long int yg = y + days / 365 - (days % 365 < 0);
+
+ /* Adjust DAYS and Y to match the guessed year. */
+ days -= ((yg - y) * 365
+ + LEAPS_THRU_END_OF (yg - 1)
+ - LEAPS_THRU_END_OF (y - 1));
+ y = yg;
+ }
+ *yearp = y - 1900;
+ yday = days; /* day in the year. Not currently used. */
+ ip = __mon_yday[__isleap(y)];
+ for (y = 11; days < (long int) ip[y]; --y)
+ continue;
+ days -= ip[y];
+ *monp = y;
+ *dayp = days + 1; /* day in the month */
+ return;
+}
+
+/*
+ * Return the boot time for use in initializing the kernel clock.
+ *
+ * I'd like to read the hardware clock here but many machines read
+ * the PRAM through ADB, and interrupts aren't initialized when this
+ * is called so ADB obviously won't work.
+ */
+
+void mac_gettod(int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ /* Yes the GMT bias is backwards. It looks like Penguin is
+ screwing up the boottime it gives us... This works for me
+ in Canada/Eastern but it might be wrong everywhere else. */
+ unmktime(mac_bi_data.boottime, -mac_bi_data.gmtbias * 60,
+ yearp, monp, dayp, hourp, minp, secp);
+ /* For some reason this is off by one */
+ *monp = *monp + 1;
+}
+
+/*
+ * Read/write the hardware clock.
+ */
+
+int mac_hwclk(int op, struct hwclk_time *t)
+{
+ unsigned long now;
+
+ if (!op) { /* read */
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ now = via_read_time();
+ } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
+ (macintosh_config->adb_type == MAC_ADB_PB1) ||
+ (macintosh_config->adb_type == MAC_ADB_PB2) ||
+ (macintosh_config->adb_type == MAC_ADB_CUDA)) {
+ now = adb_read_time();
+ } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ now = via_read_time();
+ } else {
+ now = 0;
+ }
+
+ t->wday = 0;
+ unmktime(now, 0,
+ &t->year, &t->mon, &t->day,
+ &t->hour, &t->min, &t->sec);
+ printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n",
+ t->year + 1900, t->mon + 1, t->day, t->hour, t->min, t->sec);
+ } else { /* write */
+ printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
+ t->year + 1900, t->mon + 1, t->day, t->hour, t->min, t->sec);
+
+#if 0 /* it trashes my rtc */
+ now = mktime(t->year + 1900, t->mon + 1, t->day,
+ t->hour, t->min, t->sec);
+
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ via_write_time(now);
+ } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
+ (macintosh_config->adb_type == MAC_ADB_PB1) ||
+ (macintosh_config->adb_type == MAC_ADB_PB2) ||
+ (macintosh_config->adb_type == MAC_ADB_CUDA)) {
+ adb_write_time(now);
+ } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ via_write_time(now);
+ }
+#endif
+ }
+ return 0;
+}
+
+/*
+ * Set minutes/seconds in the hardware clock
+ */
+
+int mac_set_clock_mmss (unsigned long nowtime)
+{
+ struct hwclk_time now;
+
+ mac_hwclk(0, &now);
+ now.sec = nowtime % 60;
+ now.min = (nowtime / 60) % 60;
+ mac_hwclk(1, &now);
+
+ return 0;
+}
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 442d72802..c405fc0da 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -34,7 +34,7 @@ void oss_irq(int, void *, struct pt_regs *);
void oss_nubus_irq(int, void *, struct pt_regs *);
extern void via1_irq(int, void *, struct pt_regs *);
-extern void mac_SCC_handler(int, void *, struct pt_regs *);
+extern void mac_scc_dispatch(int, void *, struct pt_regs *);
extern int console_loglevel;
/*
@@ -68,16 +68,16 @@ void __init oss_init(void)
void __init oss_register_interrupts(void)
{
- request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
- "OSS SCSI Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_IOPSCC, mac_SCC_handler, IRQ_FLG_LOCK,
- "SCC Dispatch", mac_SCC_handler);
- request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
- "Nubus Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
- "OSS Sound Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+ "scsi", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch);
+ sys_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+ "nubus", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+ "sound", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+ "via1", (void *) via1);
}
/*
@@ -89,22 +89,6 @@ void __init oss_nubus_init(void)
}
/*
- * Turn off the power via the ROM control register
- *
- * FIXME: not sure how this is supposed to work exactly...
- */
-
-void oss_poweroff(void)
-{
- oss->rom_ctrl = OSS_POWEROFF;
-
- /* We should never make it this far... */
-
- printk ("It is now safe to switch off your machine.\n");
- while(1);
-}
-
-/*
* Handle miscellaneous OSS interrupts. Right now that's just sound
* and SCSI; everything else is routed to its own autovector IRQ.
*/
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 45825b113..86bbf72cc 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -119,14 +119,14 @@ void __init psc_init(void)
void __init psc_register_interrupts(void)
{
- request_irq(3, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x30);
- request_irq(4, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x40);
- request_irq(5, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x50);
- request_irq(6, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x60);
+ sys_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3",
+ (void *) 0x30);
+ sys_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4",
+ (void *) 0x40);
+ sys_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5",
+ (void *) 0x50);
+ sys_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6",
+ (void *) 0x60);
}
/*
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 2205b226c..af001907d 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -24,6 +24,8 @@
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/ide.h>
+
#include <asm/traps.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -60,7 +62,7 @@ static int gIER,gIFR,gBufA,gBufB;
#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
-static int nubus_active;
+static int nubus_active = 0;
void via_debug_dump(void);
void via1_irq(int, void *, struct pt_regs *);
@@ -71,7 +73,7 @@ void via_irq_disable(int irq);
void via_irq_clear(int irq);
extern void mac_bang(int, void *, struct pt_regs *);
-extern void mac_SCC_handler(int, void *, struct pt_regs *);
+extern void mac_scc_dispatch(int, void *, struct pt_regs *);
extern int console_loglevel;
extern int oss_present;
@@ -260,28 +262,28 @@ void __init via_init_clock(void (*func)(int, void *, struct pt_regs *))
void __init via_register_interrupts(void)
{
if (via_alt_mapping) {
- request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "Software IRQ", (void *) via1);
- request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "software", (void *) via1);
+ sys_request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via1", (void *) via1);
} else {
- request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via1", (void *) via1);
#if 0 /* interferes with serial on some machines */
if (!psc_present) {
- request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
+ sys_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
"Off Switch", mac_bang);
}
#endif
}
- request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA2 Dispatch", (void *) via2);
+ sys_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via2", (void *) via2);
if (!psc_present) {
- request_irq(IRQ_AUTO_4, mac_SCC_handler, IRQ_FLG_LOCK,
- "SCC Dispatch", mac_SCC_handler);
+ sys_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch);
}
request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "Nubus Dispatch", (void *) via2);
+ "nubus", (void *) via2);
}
/*
@@ -361,34 +363,13 @@ int via_get_cache_disable(void)
}
/*
- * VIA-based power switch, for machines that support it.
- */
-
-void via_poweroff(void)
-{
- if (rbv_present) {
- via2[rBufB] &= ~0x04;
- } else {
- /* Direction of vDirB is output */
- via2[vDirB] |= 0x04;
- /* Send a value of 0 on that line */
- via2[vBufB] &= ~0x04;
- /* Otherwise it prints "It is now.." then shuts off */
- mdelay(1000);
- }
-
- /* We should never make it this far... */
- printk ("It is now safe to switch off your machine.\n");
- while(1);
-}
-
-/*
* Initialize VIA2 for Nubus access
*/
void __init via_nubus_init(void)
{
- nubus_active = 0;
+ /* don't set nubus_active = 0 here, it kills the Baboon */
+ /* interrupt that we've already registered. */
/* unlock nubus transactions */
@@ -396,14 +377,22 @@ void __init via_nubus_init(void)
/* set the line to be an output on non-RBV machines */
via2[vDirB] |= 0x02;
}
- via2[gBufB] |= 0x02;
+
+ /* this seems to be an ADB bit on PMU machines */
+ /* according to MkLinux. -- jmt */
+
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ via2[gBufB] |= 0x02;
+ }
/* disable nubus slot interrupts. */
if (rbv_present) {
- via2[rSIER] = 0x7F; /* like VIA; bit 7=clr,set */
+ via2[rSIER] = 0x7F;
+ via2[rSIER] = nubus_active | 0x80;
} else {
- via2[vBufA] = 0xFF; /* active low irqs, force high */
- via2[vDirA] = 0xFF; /* ddr to output. */
+ via2[vBufA] = 0xFF;
+ via2[vDirA] = ~nubus_active;
}
}
@@ -478,7 +467,7 @@ void via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
int irq_bit, i;
unsigned char events;
- if (!(events = ~via2[gBufA] & nubus_active)) return;
+ if (!(events = ~via2[gBufA] & nubus_active)) return;
for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
if (events & irq_bit) {
@@ -587,188 +576,3 @@ int via_irq_pending(int irq)
}
return 0;
}
-
-void via_scsi_clear(void)
-{
- volatile unsigned char deep_magic;
-
-#ifdef DEBUG_IRQUSE
- printk("via_scsi_clear()\n");
-#endif
-
- /* We handle this in oss.c , but this gets called in mac_scsinew.c */
- if(oss_present) return;
-
- if (rbv_present) {
- via2[rIFR] = (1<<3) | (1<<0) | rbv_clear;
- deep_magic = via2[rBufB];
- } else {
- deep_magic = via2[vBufB];
- }
- mac_enable_irq(IRQ_MAC_SCSI);
-}
-
-/*
- * PRAM/RTC access routines
- *
- * Must be called with interrupts disabled and
- * the RTC should be enabled.
- */
-
-static __u8 via_pram_readbyte(void)
-{
- int i,reg;
- __u8 data;
-
- reg = via1[vBufB] & ~VIA1B_vRTCClk;
-
- /* Set the RTC data line to be an input. */
-
- via1[vDirB] &= ~VIA1B_vRTCData;
-
- /* The bits of the byte come out in MSB order */
-
- data = 0;
- for (i = 0 ; i < 8 ; i++) {
- via1[vBufB] = reg;
- via1[vBufB] = reg | VIA1B_vRTCClk;
- data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
- }
-
- /* Return RTC data line to output state */
-
- via1[vDirB] |= VIA1B_vRTCData;
-
- return data;
-}
-
-static void via_pram_writebyte(__u8 data)
-{
- int i,reg,bit;
-
- reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
-
- /* The bits of the byte go in in MSB order */
-
- for (i = 0 ; i < 8 ; i++) {
- bit = data & 0x80? 1 : 0;
- data <<= 1;
- via1[vBufB] = reg | bit;
- via1[vBufB] = reg | bit | VIA1B_vRTCClk;
- }
-}
-
-/*
- * Execute a PRAM/RTC command. For read commands
- * data should point to a one-byte buffer for the
- * resulting data. For write commands it should point
- * to the data byte to for the command.
- *
- * This function disables all interrupts while running.
- */
-
-void via_pram_command(int command, __u8 *data)
-{
- unsigned long cpu_flags;
- int is_read;
-
- save_flags(cpu_flags);
- cli();
-
- /* Enable the RTC and make sure the strobe line is high */
-
- via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
-
- if (command & 0xFF00) { /* extended (two-byte) command */
- via_pram_writebyte((command & 0xFF00) >> 8);
- via_pram_writebyte(command & 0xFF);
- is_read = command & 0x8000;
- } else { /* one-byte command */
- via_pram_writebyte(command);
- is_read = command & 0x80;
- }
- if (is_read) {
- *data = via_pram_readbyte();
- } else {
- via_pram_writebyte(*data);
- }
-
- /* All done, disable the RTC */
-
- via1[vBufB] |= VIA1B_vRTCEnb;
-
- restore_flags(cpu_flags);
-}
-
-/*
- * Return the current time in seconds since January 1, 1904.
- *
- * This only works on machines with the VIA-based PRAM/RTC, which
- * is basically any machine with Mac II-style ADB.
- */
-
-__u32 via_read_time(void)
-{
- union {
- __u8 cdata[4];
- __u32 idata;
- } result, last_result;
- int ct;
-
- /*
- * The NetBSD guys say to loop until you get the same reading
- * twice in a row.
- */
-
- ct = 0;
- do {
- if (++ct > 10) {
- printk("via_read_time: couldn't get valid time, "
- "last read = 0x%08X and 0x%08X\n", last_result.idata,
- result.idata);
- break;
- }
-
- last_result.idata = result.idata;
- result.idata = 0;
-
- via_pram_command(0x81, &result.cdata[3]);
- via_pram_command(0x85, &result.cdata[2]);
- via_pram_command(0x89, &result.cdata[1]);
- via_pram_command(0x8D, &result.cdata[0]);
- } while (result.idata != last_result.idata);
-
- return result.idata;
-}
-
-/*
- * Set the current time to a number of seconds since January 1, 1904.
- *
- * This only works on machines with the VIA-based PRAM/RTC, which
- * is basically any machine with Mac II-style ADB.
- */
-
-void via_write_time(__u32 time)
-{
- union {
- __u8 cdata[4];
- __u32 idata;
- } data;
- __u8 temp;
-
- /* Clear the write protect bit */
-
- temp = 0x55;
- via_pram_command(0x35, &temp);
-
- data.idata = time;
- via_pram_command(0x01, &data.cdata[3]);
- via_pram_command(0x05, &data.cdata[2]);
- via_pram_command(0x09, &data.cdata[1]);
- via_pram_command(0x0D, &data.cdata[0]);
-
- /* Set the write protect bit */
-
- temp = 0xD5;
- via_pram_command(0x35, &temp);
-}
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 456520a64..146dc7279 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -207,7 +207,7 @@ void __init paging_init(void)
{
int chunk;
unsigned long mem_avail = 0;
- unsigned int zones_size[3] = { 0, };
+ unsigned long zones_size[3] = { 0, };
#ifdef DEBUG
{
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index bd59fecba..8d6632d2f 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -30,7 +30,7 @@
extern void mmu_emu_init (void);
-extern unsigned long free_area_init(unsigned long, unsigned long);
+extern unsigned long free_area_init(unsigned long *zones_size);
const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";