diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
commit | 482368b1a8e45430672c58c9a42e7d2004367126 (patch) | |
tree | ce2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /arch/m68k | |
parent | e4d0251c6f56ab2e191afb70f80f382793e23f74 (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.c | 6 | ||||
-rw-r--r-- | arch/m68k/atari/stram.c | 2 | ||||
-rw-r--r-- | arch/m68k/config.in | 38 | ||||
-rw-r--r-- | arch/m68k/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/m68k/kernel/m68k_ksyms.c | 1 | ||||
-rw-r--r-- | arch/m68k/mac/Makefile | 2 | ||||
-rw-r--r-- | arch/m68k/mac/adb-bus.c | 2699 | ||||
-rw-r--r-- | arch/m68k/mac/baboon.c | 124 | ||||
-rw-r--r-- | arch/m68k/mac/config.c | 415 | ||||
-rw-r--r-- | arch/m68k/mac/iop.c | 2 | ||||
-rw-r--r-- | arch/m68k/mac/macints.c | 304 | ||||
-rw-r--r-- | arch/m68k/mac/mackeyb.c | 762 | ||||
-rw-r--r-- | arch/m68k/mac/misc.c | 689 | ||||
-rw-r--r-- | arch/m68k/mac/oss.c | 38 | ||||
-rw-r--r-- | arch/m68k/mac/psc.c | 16 | ||||
-rw-r--r-- | arch/m68k/mac/via.c | 258 | ||||
-rw-r--r-- | arch/m68k/mm/motorola.c | 2 | ||||
-rw-r--r-- | arch/m68k/mm/sun3mmu.c | 2 |
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"; |