summaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/macintosh')
-rw-r--r--drivers/macintosh/Makefile7
-rw-r--r--drivers/macintosh/adb.c26
-rw-r--r--drivers/macintosh/mac_keyb.c170
-rw-r--r--drivers/macintosh/macio-adb.c23
-rw-r--r--drivers/macintosh/macserial.c89
-rw-r--r--drivers/macintosh/macserial.h3
-rw-r--r--drivers/macintosh/mediabay.c308
-rw-r--r--drivers/macintosh/via-cuda.c20
-rw-r--r--drivers/macintosh/via-pmu.c102
9 files changed, 518 insertions, 230 deletions
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6ab7eba3a..74086d99b 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -16,14 +16,15 @@ L_TARGET := macintosh.a
M_OBJS :=
ifndef CONFIG_MBX
-L_OBJS := via-cuda.o adb.o nvram.o macio-adb.o via-pmu.o mediabay.o
+L_OBJS := via-cuda.o nvram.o macio-adb.o via-pmu.o mediabay.o
+LX_OBJS := adb.o
endif
ifeq ($(CONFIG_MAC_SERIAL),y)
- LX_OBJS += macserial.o
+ L_OBJS += macserial.o
else
ifeq ($(CONFIG_MAC_SERIAL),m)
- MX_OBJS += macserial.o
+ M_OBJS += macserial.o
endif
endif
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 4c9a67cc0..4bcd1715b 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -8,6 +8,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
+#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
@@ -19,10 +20,13 @@
#include <asm/hydra.h>
#include <asm/init.h>
+EXPORT_SYMBOL(adb_hardware);
+
enum adb_hw adb_hardware = ADB_NONE;
int (*adb_send_request)(struct adb_request *req, int sync);
-int (*adb_autopoll)(int on);
-static void adb_scan_bus(void);
+int (*adb_autopoll)(int devs);
+int (*adb_reset_bus)(void);
+static int adb_scan_bus(void);
static struct adb_handler {
void (*handler)(unsigned char *, int, struct pt_regs *, int);
@@ -50,13 +54,13 @@ static void printADBreply(struct adb_request *req)
}
#endif
-static void adb_scan_bus(void)
+static int adb_scan_bus(void)
{
int i, highFree=0, noMovement;
+ int devmask = 0;
struct adb_request req;
- /* reset ADB bus */
- /*adb_request(&req, NULL, ADBREQ_SYNC, 1, 0);*/
+ adb_reset_bus(); /* reset ADB bus */
/* assumes adb_handler[] is all zeroes at this point */
for (i = 1; i < 16; i++) {
@@ -134,24 +138,27 @@ static void adb_scan_bus(void)
adb_handler[i].handler_id = req.reply[2];
printk(" [%d]: %d %x", i, adb_handler[i].original_address,
adb_handler[i].handler_id);
+ devmask |= 1 << i;
}
printk("\n");
+ return devmask;
}
void adb_init(void)
{
adb_send_request = (void *) adb_nodev;
adb_autopoll = (void *) adb_nodev;
+ adb_reset_bus = adb_nodev;
if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
- return;
+ return;
via_cuda_init();
via_pmu_init();
macio_adb_init();
if (adb_hardware == ADB_NONE)
printk(KERN_WARNING "Warning: no ADB interface detected\n");
else {
- adb_scan_bus();
- adb_autopoll(1);
+ int devs = adb_scan_bus();
+ adb_autopoll(devs);
}
}
@@ -187,8 +194,7 @@ adb_register(int default_id, int handler_id, struct adb_ids *ids,
ids->nids = 0;
for (i = 1; i < 16; i++) {
- if ((adb_handler[i].original_address == default_id) ||
- (adb_handler[i].handler_id == handler_id)) {
+ if (adb_handler[i].original_address == default_id) {
if (adb_handler[i].handler != 0) {
printk(KERN_ERR
"Two handlers for ADB device %d\n",
diff --git a/drivers/macintosh/mac_keyb.c b/drivers/macintosh/mac_keyb.c
index 5c49af36f..c2ff83b83 100644
--- a/drivers/macintosh/mac_keyb.c
+++ b/drivers/macintosh/mac_keyb.c
@@ -16,6 +16,8 @@
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/tty_flip.h>
+#include <linux/config.h>
#include <asm/bitops.h>
#include <asm/adb.h>
@@ -170,16 +172,22 @@ static int last_keycode;
static void keyboard_input(unsigned char *, int, struct pt_regs *, int);
static void input_keycode(int, int);
static void leds_done(struct adb_request *);
+static void mac_put_queue(int);
+#ifdef CONFIG_ADBMOUSE
/* XXX: Hook for mouse driver */
-void (*adb_mouse_interrupt_hook) (char *, int);
-static int adb_emulate_buttons = 0;
+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
+
extern int console_loglevel;
extern struct kbd_struct kbd_table[];
+extern struct wait_queue * keypress_wait;
extern void handle_scancode(unsigned char);
-extern void put_queue(int);
static struct adb_ids keyboard_ids;
static struct adb_ids mouse_ids;
@@ -264,6 +272,7 @@ input_keycode(int keycode, int repeat)
if (!repeat)
del_timer(&repeat_timer);
+#ifdef CONFIG_ADBMOUSE
/*
* XXX: Add mouse button 2+3 fake codes here if mouse open.
* Keep track of 'button' states here as we only send
@@ -273,52 +282,27 @@ input_keycode(int keycode, int repeat)
* Might also want to know how many buttons need to be emulated.
* -> hide this as function in arch/m68k/mac ?
*/
- if ( (adb_emulate_buttons) &&
- (adb_mouse_interrupt_hook || console_loglevel == 10) ) {
- unsigned char button, button2, button3, fake_event;
- static unsigned char button2state=0, button3state=0; /* up */
+ if (adb_emulate_buttons
+ && (keycode == adb_button2_keycode
+ || keycode == adb_button3_keycode)
+ && (adb_mouse_interrupt_hook || console_loglevel == 10)) {
+ int button;
/* faked ADB packet */
- static char data[4] = { 0, 0x80, 0x80, 0x80 };
-
- button = 0;
- fake_event = 0;
- switch (keycode) { /* which 'button' ? */
- case 0x7c: /* R-option */
- button3 = (!up_flag); /* new state */
- if (button3 != button3state) /* change ? */
- button = 3;
- button3state = button3; /* save state */
- fake_event = 3;
- break;
- case 0x7d: /* R-control */
- button2 = (!up_flag); /* new state */
- if (button2 != button2state) /* change ? */
- button = 2;
- button2state = button2; /* save state */
- fake_event = 2;
- break;
- }
- if (fake_event && console_loglevel >= 8)
- printk("fake event: button2 %d button3 %d button %d\n",
- button2state, button3state, button);
- if (button) { /* there's been a button state change */
- /* fake a mouse packet : send all bytes, change one! */
- data[button] = (up_flag ? 0x80 : 0);
+ static unsigned char data[4] = { 0, 0x80, 0x80, 0x80 };
+
+ button = keycode == adb_button2_keycode? 2: 3;
+ if (data[button] != up_flag) {
+ /* send a fake mouse packet */
+ data[button] = up_flag;
+ if (console_loglevel >= 8)
+ printk("fake mouse event: %x %x %x\n",
+ data[1], data[2], data[3]);
if (adb_mouse_interrupt_hook)
- adb_mouse_interrupt_hook(data, -1);
- else
- printk("mouse_fake: data %x %x %x buttons %x \n",
- data[1], data[2], data[3],
- ~( (data[1] & 0x80 ? 0 : 4)
- | (data[2] & 0x80 ? 0 : 1)
- | (data[3] & 0x80 ? 0 : 2) )&7 );
+ adb_mouse_interrupt_hook(data, 4);
}
- /*
- * XXX: testing mouse emulation ... don't process fake keys!
- */
- if (fake_event)
- return;
+ return;
}
+#endif /* CONFIG_ADBMOUSE */
if (kbd->kbdmode != VC_RAW) {
if (!up_flag && !dont_repeat[keycode]) {
@@ -361,6 +345,20 @@ kbd_repeat(unsigned long xxx)
restore_flags(flags);
}
+static void mac_put_queue(int ch)
+{
+ extern struct tty_driver console_driver;
+ struct tty_struct *tty;
+
+ tty = console_driver.table? console_driver.table[fg_console]: NULL;
+ wake_up(&keypress_wait);
+ if (tty) {
+ tty_insert_flip_char(tty, ch, 0);
+ con_schedule_flip(tty);
+ }
+}
+
+#ifdef CONFIG_ADBMOUSE
static void
mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
{
@@ -399,62 +397,34 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
*/
/*
+ 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] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+ data[1] = bxxx xxxx First button and x-axis motion.
+ data[2] = byyy yyyy Second button and y-axis motion.
+
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
+ data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+ data[1] = bxxx xxxx Left button and x-axis motion.
+ data[2] = byyy yyyy Second button and y-axis motion.
+ data[3] = 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.
*/
struct kbd_struct *kbd;
if (adb_mouse_interrupt_hook)
adb_mouse_interrupt_hook(data, nb);
- else
- if (console_loglevel == 10)
- printk("mouse_input: data %x %x %x buttons %x dx %d dy %d \n",
- data[1], data[2], data[3],
- ~((data[1] & 0x80 ? 0 : 4)
- | (data[2] & 0x80 ? 0 : 1)
- | (data[3] & 0x80 ? 0 : 2))&7,
- ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ),
- ((data[1]&0x7f) < 64 ? -(data[1]&0x7f) : 128-(data[1]&0x7f) ) );
kbd = kbd_table + fg_console;
@@ -464,9 +434,9 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
unsigned char uchButtonSecond;
/* Send first button, second button and movement. */
- put_queue( 0x7e );
- put_queue( data[1] );
- put_queue( data[2] );
+ mac_put_queue(0x7e);
+ mac_put_queue(data[1]);
+ mac_put_queue(data[2]);
/* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */
@@ -475,12 +445,12 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
/* Send second button. */
if (uchButtonSecond != uch_ButtonStateSecond) {
- put_queue( 0x3f | uchButtonSecond );
+ mac_put_queue(0x3f | uchButtonSecond);
uch_ButtonStateSecond = uchButtonSecond;
}
/* Macintosh 3-button mouse (handler 4). */
- if ((nb == 4) && autopoll /*?*/) {
+ if (nb == 4) {
static unsigned char uch_ButtonStateThird = 0x80;
unsigned char uchButtonThird;
@@ -489,12 +459,13 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
/* Send third button. */
if (uchButtonThird != uch_ButtonStateThird) {
- put_queue( 0x40 | uchButtonThird );
+ mac_put_queue(0x40 | uchButtonThird);
uch_ButtonStateThird = uchButtonThird;
}
}
}
}
+#endif /* CONFIG_ADBMOUSE */
/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
static unsigned char mac_ledmap[8] = {
@@ -571,11 +542,14 @@ __initfunc(void mackbd_init_hw(void))
memcpy(key_maps[8], macalt_map, sizeof(plain_map));
memcpy(key_maps[12], macctrl_alt_map, sizeof(plain_map));
+#ifdef CONFIG_ADBMOUSE
/* initialize mouse interrupt hook */
adb_mouse_interrupt_hook = NULL;
- adb_register(ADB_KEYBOARD, 5, &keyboard_ids, keyboard_input);
adb_register(ADB_MOUSE, 1, &mouse_ids, mouse_input);
+#endif /* CONFIG_ADBMOUSE */
+
+ adb_register(ADB_KEYBOARD, 5, &keyboard_ids, keyboard_input);
for(i = 0; i < keyboard_ids.nids; i++) {
/* turn off all leds */
@@ -634,9 +608,3 @@ __initfunc(void mackbd_init_hw(void))
}
}
}
-
-void adb_setup_mouse( char *s, int *ints )
-{
- if (ints[0] >= 1)
- adb_emulate_buttons = ints[1];
-}
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index 0af447c08..b3e7b0ec2 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -61,8 +61,9 @@ static unsigned char adb_rbuf[16];
static void macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
static int macio_adb_send_request(struct adb_request *req, int sync);
-static int macio_adb_autopoll(int on);
+static int macio_adb_autopoll(int devs);
static void macio_adb_poll(void);
+static int macio_reset_bus(void);
static void completed(void);
__openfirmware
@@ -108,14 +109,30 @@ void macio_adb_init(void)
adb_hardware = ADB_MACIO;
adb_send_request = macio_adb_send_request;
adb_autopoll = macio_adb_autopoll;
+ adb_reset_bus = macio_reset_bus;
}
-static int macio_adb_autopoll(int on)
+static int macio_adb_autopoll(int devs)
{
- out_8(&adb->autopoll.r, on? APE: 0);
+ out_8(&adb->active_hi.r, devs >> 8);
+ out_8(&adb->active_lo.r, devs);
+ out_8(&adb->autopoll.r, devs? APE: 0);
return 0;
}
+static int macio_reset_bus(void)
+{
+ int timeout = 1000000;
+
+ out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | ADB_RST);
+ while ((in_8(&adb->ctrl.r) & ADB_RST) != 0) {
+ if (--timeout == 0) {
+ out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) & ~ADB_RST);
+ return -1;
+ }
+ }
+ return 0;
+}
/* Send an ADB command */
static int macio_adb_send_request(struct adb_request *req, int sync)
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 7c8cf23d8..5af8ad871 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -33,6 +33,7 @@
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
+#include <asm/feature.h>
#ifdef CONFIG_KGDB
#include <asm/kgdb.h>
#endif
@@ -165,25 +166,35 @@ static inline unsigned char read_zsreg(struct mac_zschannel *channel,
unsigned char reg)
{
unsigned char retval;
+ unsigned long flags;
+ /*
+ * We have to make this atomic.
+ */
+ spin_lock_irqsave(&channel->lock, flags);
if (reg != 0) {
*channel->control = reg;
RECOVERY_DELAY;
}
retval = *channel->control;
RECOVERY_DELAY;
+ spin_unlock_irqrestore(&channel->lock, flags);
return retval;
}
static inline void write_zsreg(struct mac_zschannel *channel,
unsigned char reg, unsigned char value)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&channel->lock, flags);
if (reg != 0) {
*channel->control = reg;
RECOVERY_DELAY;
}
*channel->control = value;
RECOVERY_DELAY;
+ spin_unlock_irqrestore(&channel->lock, flags);
return;
}
@@ -434,6 +445,10 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
for (;;) {
zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift;
+#ifdef SERIAL_DEBUG_INTR
+// printk("rs_interrupt: irq %d, zs_intreg 0x%x\n", irq, (int)zs_intreg);
+#endif
+
if ((zs_intreg & CHAN_IRQMASK) == 0)
break;
@@ -1261,17 +1276,26 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
tty->closing = 0;
info->event = 0;
info->tty = 0;
+
+ if (info->is_cobalt_modem) {
+ /* Power down modem */
+ feature_set(info->dev_node, FEATURE_Modem_Reset);
+ mdelay(15);
+ feature_clear(info->dev_node, FEATURE_Modem_PowerOn);
+ mdelay(15);
+ }
+
if (info->blocked_open) {
if (info->close_delay) {
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + info->close_delay;
- schedule();
+ schedule_timeout(info->close_delay);
}
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
ZILOG_CLOSING);
wake_up_interruptible(&info->close_wait);
+
restore_flags(flags);
}
@@ -1301,8 +1325,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
current->state = TASK_INTERRUPTIBLE;
current->counter = 0; /* make us low-priority */
- current->timeout = jiffies + char_time;
- schedule();
+ schedule_timeout(char_time);
if (signal_pending(current))
break;
if (timeout && ((orig_jiffies + timeout) < jiffies))
@@ -1510,9 +1533,25 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
/*
* Start up serial port
*/
+
+ if (info->is_cobalt_modem) {
+ /* Power up modem */
+ feature_set(info->dev_node, FEATURE_Modem_PowerOn);
+ mdelay(250);
+ feature_clear(info->dev_node, FEATURE_Modem_Reset);
+ mdelay(10);
+ }
retval = startup(info);
- if (retval)
+ if (retval) {
+ if (info->is_cobalt_modem) {
+ /* Power down modem */
+ feature_set(info->dev_node, FEATURE_Modem_Reset);
+ mdelay(15);
+ feature_clear(info->dev_node, FEATURE_Modem_PowerOn);
+ mdelay(15);
+ }
return retval;
+ }
retval = block_til_ready(tty, filp, info);
if (retval) {
@@ -1520,6 +1559,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
+ if (info->is_cobalt_modem) {
+ /* Power down modem */
+ feature_set(info->dev_node, FEATURE_Modem_Reset);
+ mdelay(15);
+ feature_clear(info->dev_node, FEATURE_Modem_PowerOn);
+ mdelay(15);
+ }
return retval;
}
@@ -1570,8 +1616,14 @@ probe_sccs()
dev->full_name);
continue;
}
+ feature_clear(dev, FEATURE_Serial_reset);
+ mdelay(5);
+ feature_set(dev, FEATURE_Serial_enable);
+ feature_set(dev, FEATURE_Serial_IO_A);
+ feature_set(dev, FEATURE_Serial_IO_B);
+ mdelay(5);
for (ch = dev->child; ch != 0; ch = ch->sibling) {
- if (ch->n_addrs < 1 || ch ->n_intrs < 1) {
+ if (ch->n_addrs < 1 || (ch ->n_intrs < 1)) {
printk("Can't use %s: %d addrs %d intrs\n",
ch->full_name, ch->n_addrs, ch->n_intrs);
continue;
@@ -1580,8 +1632,20 @@ probe_sccs()
ioremap(ch->addrs[0].address, 0x1000);
zs_channels[n].data = zs_channels[n].control
+ ch->addrs[0].size / 2;
+ spin_lock_init(&zs_channels[n].lock);
zs_soft[n].zs_channel = &zs_channels[n];
+ zs_soft[n].dev_node = ch;
zs_soft[n].irq = ch->intrs[0].line;
+ zs_soft[n].is_cobalt_modem = device_is_compatible(ch, "cobalt");
+ if (zs_soft[n].is_cobalt_modem)
+ {
+ /* Just in case the modem is up, shut it down */
+ feature_set(ch, FEATURE_Modem_Reset);
+ mdelay(15);
+ feature_clear(ch, FEATURE_Modem_PowerOn);
+ mdelay(15);
+ }
+
/* XXX this assumes the prom puts chan A before B */
if (n & 1)
zs_soft[n].zs_chan_a = &zs_channels[n-1];
@@ -1698,6 +1762,9 @@ int macserial_init(void)
for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
{
+ unsigned char* connector;
+ int lenp;
+
#ifdef CONFIG_KGDB
if (info->kgdb_channel) {
continue;
@@ -1721,8 +1788,14 @@ int macserial_init(void)
info->open_wait = 0;
info->close_wait = 0;
printk("tty%02d at 0x%08x (irq = %d)", info->line,
- info->port, info->irq);
- printk(" is a Z8530 ESCC\n");
+ info->port, info->irq);
+ printk(" is a Z8530 ESCC");
+ connector = get_property(info->dev_node, "AAPL,connector", &lenp);
+ if (connector)
+ printk(", port = %s", connector);
+ if (info->is_cobalt_modem)
+ printk(" (cobalt modem)");
+ printk("\n");
}
restore_flags(flags);
diff --git a/drivers/macintosh/macserial.h b/drivers/macintosh/macserial.h
index 83e6dc932..ec7552f96 100644
--- a/drivers/macintosh/macserial.h
+++ b/drivers/macintosh/macserial.h
@@ -84,6 +84,7 @@ struct serial_struct {
struct mac_zschannel {
volatile unsigned char *control;
volatile unsigned char *data;
+ spinlock_t lock;
};
struct mac_serial {
@@ -91,11 +92,13 @@ struct mac_serial {
struct mac_zschannel *zs_channel; /* Channel registers */
struct mac_zschannel *zs_chan_a; /* A side registers */
unsigned char read_reg_zero;
+ struct device_node* dev_node;
char soft_carrier; /* Use soft carrier on this channel */
char break_abort; /* Is serial console in, so process brk/abrt */
char kgdb_channel; /* Kgdb is running on this channel */
char is_cons; /* Is this our console. */
+ char is_cobalt_modem; /* is a gatwick-based cobalt modem */
unsigned char tx_active; /* character is being xmitted */
unsigned char tx_stopped; /* output is suspended */
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 53f7ab62e..13ce064f4 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -8,6 +8,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#define __KERNEL_SYSCALLS__
+
#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -16,44 +18,54 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/hdreg.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/io.h>
-#include <asm/ohare.h>
+#include <asm/feature.h>
#include <asm/mediabay.h>
#include <asm/init.h>
+
+#undef MB_USE_INTERRUPTS
+
struct media_bay_hw {
unsigned char b0;
unsigned char contents;
unsigned char b2;
unsigned char b3;
- unsigned feature;
};
-static volatile struct media_bay_hw *mb_addr;
+struct media_bay_info {
+ volatile struct media_bay_hw* addr;
+ int content_id;
+ int previous_id;
+ int ready;
+ int last_value;
+ int value_count;
+ int reset_timer;
+ struct device_node* dev_node;
+#ifdef CONFIG_BLK_DEV_IDE
+ unsigned long cd_base;
+ int cd_index;
+ int cd_irq;
+ int cd_timer;
+#endif
+};
-#define MB_CONTENTS() ((in_8(&mb_addr->contents) >> 4) & 7)
-#define SET_FEATURES(set, clr) \
- out_le32(&mb_addr->feature, \
- (in_le32(&mb_addr->feature) & ~(clr)) | (set));
+#define MAX_BAYS 2
-static int media_bay_id = -1;
-static int mb_ready;
-static int mb_last_value;
-static int mb_value_count;
+static volatile struct media_bay_info media_bays[MAX_BAYS];
+int media_bay_count = 0;
-int media_bay_present;
+#define MB_CONTENTS(i) ((in_8(&media_bays[i].addr->contents) >> 4) & 7)
#ifdef CONFIG_BLK_DEV_IDE
-unsigned long mb_cd_base;
-int mb_cd_index = -1;
-int mb_cd_irq;
-
/* check the busy bit in the media-bay ide interface
(assumes the media-bay contains an ide device) */
-#define MB_IDE_READY() ((in_8((volatile unsigned char *) \
- (mb_cd_base + 0x70)) & 0x80) == 0)
+#define MB_IDE_READY(i) ((in_8((volatile unsigned char *) \
+ (media_bays[i].cd_base + 0x70)) & 0x80) == 0)
#endif
/*
@@ -66,16 +78,17 @@ int mb_cd_irq;
* Hold the media-bay reset signal true for this many ticks
* after a device is inserted before releasing it.
*/
-#define MB_RESET_COUNT 10
+#define MB_RESET_COUNT 20
/*
* Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted
* (or until the device is ready) before registering the IDE interface.
*/
-#define MB_IDE_WAIT 500
+#define MB_IDE_WAIT 1000
-static void poll_media_bay(void);
-static void set_media_bay(int id);
+static void poll_media_bay(int which);
+static void set_media_bay(int which, int id);
+static int media_bay_task(void *);
/*
* It seems that the bit for the media-bay interrupt in the IRQ_LEVEL
@@ -92,29 +105,62 @@ void
media_bay_init(void)
{
struct device_node *np;
-
+ int n,i;
+
+ for (i=0; i<MAX_BAYS; i++)
+ {
+ memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info));
+ media_bays[i].content_id = -1;
+#ifdef CONFIG_BLK_DEV_IDE
+ media_bays[i].cd_index = -1;
+#endif
+ }
+
np = find_devices("media-bay");
- if (np == NULL || np->n_addrs == 0)
- return;
- mb_addr = (volatile struct media_bay_hw *)
- ioremap(np->addrs[0].address, sizeof(struct media_bay_hw));
+ n = 0;
+ while(np && (n<MAX_BAYS))
+ {
+ if (np->n_addrs == 0)
+ continue;
+ media_bays[n].addr = (volatile struct media_bay_hw *)
+ ioremap(np->addrs[0].address, sizeof(struct media_bay_hw));
-#if 0
- if (np->n_intrs == 0) {
- printk(KERN_WARNING "No interrupt for media bay?\n");
- } else {
- if (request_irq(np->intrs[0].line, media_bay_intr, 0,
- "Media bay", NULL))
- printk(KERN_WARNING "Couldn't get IRQ %d for "
- "media bay\n", np->intrs[0].line);
- }
+#ifdef MB_USE_INTERRUPTS
+ if (np->n_intrs == 0)
+ {
+ printk(KERN_ERR "media bay %d has no irq\n",n);
+ continue;
+ }
+
+ if (request_irq(np_intrs[0].line, media_bay_intr, 0, "Media bay", NULL))
+ {
+ printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", irq, n);
+ continue;
+ }
+#endif
+ media_bay_count++;
+
+ set_media_bay(n, MB_CONTENTS(n));
+ if (media_bays[n].content_id != MB_NO) {
+ feature_clear(media_bays[n].dev_node, FEATURE_Mediabay_reset);
+ udelay(500);
+ }
+ media_bays[n].ready = 1;
+ media_bays[n].previous_id = media_bays[n].content_id;
+ media_bays[n].reset_timer = 0;
+ media_bays[n].dev_node = np;
+#ifdef CONFIG_BLK_DEV_IDE
+ media_bays[n].cd_timer = 0;
#endif
+ n++;
+ np=np->next;
+ }
+
+ if (media_bay_count)
+ {
+ printk(KERN_INFO "Registered %d media-bay(s)\n", media_bay_count);
- media_bay_present = 1;
- set_media_bay(MB_CONTENTS());
- if (media_bay_id != MB_NO) {
- SET_FEATURES(0, OH_BAY_RESET);
- mb_ready = 1;
+ kernel_thread(media_bay_task, NULL, 0);
}
}
@@ -130,9 +176,61 @@ media_bay_intr(int irq, void *devid, struct pt_regs *regs)
#endif
int
-check_media_bay(int what)
+check_media_bay(struct device_node *which_bay, int what)
+{
+#ifdef CONFIG_BLK_DEV_IDE
+ int i;
+
+ for (i=0; i<media_bay_count; i++)
+ if (which_bay == media_bays[i].dev_node)
+ {
+ if ((what == media_bays[i].content_id) && media_bays[i].ready)
+ return 0;
+ media_bays[i].cd_index = -1;
+ return -EINVAL;
+ }
+#endif /* CONFIG_BLK_DEV_IDE */
+ return -ENODEV;
+}
+
+int
+check_media_bay_by_base(unsigned long base, int what)
+{
+ int i;
+
+#ifdef CONFIG_BLK_DEV_IDE
+ for (i=0; i<media_bay_count; i++)
+ if (base == media_bays[i].cd_base)
+ {
+ if ((what == media_bays[i].content_id) && media_bays[i].ready)
+ return 0;
+ media_bays[i].cd_index = -1;
+ return -EINVAL;
+ }
+#endif
+
+ return -ENODEV;
+}
+
+int
+media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+ int irq, int index)
{
- return what == media_bay_id && mb_ready;
+ int i;
+
+#ifdef CONFIG_BLK_DEV_IDE
+ for (i=0; i<media_bay_count; i++)
+ if (which_bay == media_bays[i].dev_node)
+ {
+ media_bays[i].cd_base = base;
+ media_bays[i].cd_irq = irq;
+ media_bays[i].cd_index = index;
+ printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i);
+ return 0;
+ }
+#endif
+
+ return -ENODEV;
}
/*
@@ -144,96 +242,112 @@ check_media_bay(int what)
int
media_bay_task(void *x)
{
- int prev = media_bay_id;
- int reset_timer = 0;
-#ifdef CONFIG_BLK_DEV_IDE
- int cd_timer = 0;
-#endif
-
+ volatile struct media_bay_info* bay;
+ int i = 0;
+
strcpy(current->comm, "media-bay");
- for (;;) {
- poll_media_bay();
- if (media_bay_id != prev) {
- reset_timer = (media_bay_id != MB_NO)?
+ for (;;)
+ {
+ bay = &media_bays[i];
+ poll_media_bay(i);
+ if (bay->content_id != bay->previous_id) {
+ bay->reset_timer = (bay->content_id != MB_NO) ?
MB_RESET_COUNT: 0;
- mb_ready = 0;
+ bay->ready = 0;
#ifdef CONFIG_BLK_DEV_IDE
- cd_timer = 0;
- if (media_bay_id != MB_CD && mb_cd_index >= 0) {
- printk(KERN_DEBUG "Unregistering mb ide\n");
- ide_unregister(mb_cd_index);
- mb_cd_index = -1;
+ bay->cd_timer = 0;
+ if (bay->content_id != MB_CD && bay->cd_index >= 0) {
+ printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index);
+ ide_unregister(bay->cd_index);
+ bay->cd_index = -1;
}
#endif
- } else if (reset_timer) {
- if (--reset_timer == 0) {
- SET_FEATURES(0, OH_BAY_RESET);
- mb_ready = 1;
+ } else if (bay->reset_timer) {
+ if (--bay->reset_timer == 0) {
+ feature_clear(bay->dev_node, FEATURE_Mediabay_reset);
+ bay->ready = 1;
#ifdef CONFIG_BLK_DEV_IDE
- if (media_bay_id == MB_CD && mb_cd_base != 0)
- cd_timer = MB_IDE_WAIT;
+ bay->cd_timer = 0;
+ if (bay->content_id == MB_CD && bay->cd_base != 0)
+ bay->cd_timer = MB_IDE_WAIT;
#endif
}
#ifdef CONFIG_BLK_DEV_IDE
- } else if (cd_timer && (--cd_timer == 0 || MB_IDE_READY())
- && mb_cd_index < 0) {
- mb_cd_index = ide_register(mb_cd_base, 0, mb_cd_irq);
- printk(KERN_DEBUG "media-bay is ide %d\n", mb_cd_index);
+ } else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i))
+ && bay->cd_index < 0) {
+ bay->cd_timer = 0;
+ printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq);
+ printk("\n");
+ bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq);
+ if (bay->cd_index == -1)
+ printk("\nCD-ROM badly inserted. Remove it and try again !\n");
+ else
+ printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index);
#endif
}
- prev = media_bay_id;
+ bay->previous_id = bay->content_id;
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
+ schedule_timeout(1);
if (signal_pending(current))
return 0;
+ i = (i+1)%media_bay_count;
}
}
void
-poll_media_bay(void)
+poll_media_bay(int which)
{
- int id = MB_CONTENTS();
+ int id = MB_CONTENTS(which);
- if (id == mb_last_value) {
- if (id != media_bay_id
- && ++mb_value_count >= MB_STABLE_COUNT)
- set_media_bay(id);
+ if (id == media_bays[which].last_value) {
+ if (id != media_bays[which].content_id
+ && ++media_bays[which].value_count >= MB_STABLE_COUNT)
+ set_media_bay(which, id);
} else {
- mb_last_value = id;
- mb_value_count = 0;
+ media_bays[which].last_value = id;
+ media_bays[which].value_count = 0;
}
}
static void
-set_media_bay(int id)
+set_media_bay(int which, int id)
{
- u32 clr, set;
+ volatile struct media_bay_info* bay;
- media_bay_id = id;
- mb_last_value = id;
- clr = OH_FLOPPY_ENABLE | OH_IDECD_POWER;
- set = 0;
+ bay = &media_bays[which];
+
+ bay->content_id = id;
+ bay->last_value = id;
+
switch (id) {
case MB_CD:
- set = OH_BAY_ENABLE | OH_IDECD_POWER | OH_BAY_IDE_ENABLE;
- printk(KERN_INFO "media bay contains a CD-ROM drive\n");
+ feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
+ feature_set(bay->dev_node, FEATURE_Mediabay_enable);
+ feature_set(bay->dev_node, FEATURE_CD_power);
+ feature_set(bay->dev_node, FEATURE_Mediabay_IDE_enable);
+ printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which);
break;
case MB_FD:
- set = OH_BAY_ENABLE | OH_BAY_FLOPPY_ENABLE | OH_FLOPPY_ENABLE;
- printk(KERN_INFO "media bay contains a floppy disk drive\n");
+ feature_clear(bay->dev_node, FEATURE_CD_power);
+ feature_set(bay->dev_node, FEATURE_Mediabay_enable);
+ feature_set(bay->dev_node, FEATURE_Mediabay_floppy_enable);
+ feature_set(bay->dev_node, FEATURE_SWIM3_enable);
+ printk(KERN_INFO "media bay %d contains a floppy disk drive\n", which);
break;
case MB_NO:
- printk(KERN_INFO "media bay is empty\n");
+ feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
+ feature_clear(bay->dev_node, FEATURE_CD_power);
+ printk(KERN_INFO "media bay %d is empty\n", which);
break;
default:
- set = OH_BAY_ENABLE;
- printk(KERN_INFO "media bay contains an unknown device (%d)\n",
- id);
+ feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
+ feature_clear(bay->dev_node, FEATURE_CD_power);
+ feature_set(bay->dev_node, FEATURE_Mediabay_enable);
+ printk(KERN_INFO "media bay %d contains an unknown device (%d)\n",
+ which, id);
break;
}
-
- SET_FEATURES(set, clr);
- printk(KERN_DEBUG "feature reg now %x\n", in_le32(&mb_addr->feature));
+
+ udelay(500);
}
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 986cdd7b5..b0b7dd7d2 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -80,7 +80,8 @@ static void cuda_start(void);
static void via_interrupt(int irq, void *arg, struct pt_regs *regs);
static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
static int cuda_adb_send_request(struct adb_request *req, int sync);
-static int cuda_adb_autopoll(int on);
+static int cuda_adb_autopoll(int devs);
+static int cuda_reset_bus(void);
__openfirmware
@@ -141,6 +142,7 @@ via_cuda_init(void)
/* Set function pointers */
adb_send_request = cuda_adb_send_request;
adb_autopoll = cuda_adb_autopoll;
+ adb_reset_bus = cuda_reset_bus;
}
#define WAIT_FOR(cond, what) \
@@ -216,11 +218,23 @@ cuda_adb_send_request(struct adb_request *req, int sync)
/* Enable/disable autopolling */
static int
-cuda_adb_autopoll(int on)
+cuda_adb_autopoll(int devs)
{
struct adb_request req;
- cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, on);
+ cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));
+ while (!req.complete)
+ cuda_poll();
+ return 0;
+}
+
+/* Reset adb bus - how do we do this?? */
+static int
+cuda_reset_bus(void)
+{
+ struct adb_request req;
+
+ cuda_request(&req, NULL, 2, ADB_PACKET, 0); /* maybe? */
while (!req.complete)
cuda_poll();
return 0;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 407a93002..4dd82fef9 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -30,6 +30,7 @@
#include <asm/system.h>
#include <asm/init.h>
#include <asm/irq.h>
+#include <asm/feature.h>
/* Misc minor number allocated for /dev/pmu */
#define PMU_MINOR 154
@@ -99,7 +100,8 @@ static int pmu_queue_request(struct adb_request *req);
static void pmu_start(void);
static void via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
static int pmu_adb_send_request(struct adb_request *req, int sync);
-static int pmu_adb_autopoll(int on);
+static int pmu_adb_autopoll(int devs);
+static int pmu_reset_bus(void);
static void send_byte(int x);
static void recv_byte(void);
static void pmu_sr_intr(struct pt_regs *regs);
@@ -162,6 +164,8 @@ find_via_pmu()
return;
if (vias->next != 0)
printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
+
+ feature_set(vias, FEATURE_VIA_enable);
#if 0
{ int i;
@@ -215,6 +219,7 @@ via_pmu_init(void)
/* Set function pointers */
adb_send_request = pmu_adb_send_request;
adb_autopoll = pmu_adb_autopoll;
+ adb_reset_bus = pmu_reset_bus;
}
static int
@@ -281,11 +286,12 @@ pmu_adb_send_request(struct adb_request *req, int sync)
/* Enable/disable autopolling */
static int
-pmu_adb_autopoll(int on)
+pmu_adb_autopoll(int devs)
{
struct adb_request req;
- if (on) {
+ if (devs) {
+ adb_dev_map = devs;
pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,
adb_dev_map >> 8, adb_dev_map);
pmu_adb_flags = 2;
@@ -298,6 +304,49 @@ pmu_adb_autopoll(int on)
return 0;
}
+/* Reset the ADB bus */
+static int
+pmu_reset_bus(void)
+{
+ struct adb_request req;
+ long timeout;
+ int save_autopoll = adb_dev_map;
+
+ /* anyone got a better idea?? */
+ pmu_adb_autopoll(0);
+
+ req.nbytes = 5;
+ req.done = NULL;
+ req.data[0] = PMU_ADB_CMD;
+ req.data[1] = 0;
+ req.data[2] = 3;
+ req.data[3] = 0;
+ req.data[4] = 0;
+ req.reply_len = 0;
+ req.reply_expected = 1;
+ if (pmu_queue_request(&req) != 0)
+ {
+ printk(KERN_ERR "pmu_reset_bus: pmu_queue_request failed\n");
+ return 0;
+ }
+ while (!req.complete)
+ pmu_poll();
+ timeout = 100000;
+ while (!req.complete) {
+ if (--timeout < 0) {
+ printk(KERN_ERR "pmu_reset_bus (reset): no response from PMU\n");
+ return 0;
+ }
+ udelay(10);
+ pmu_poll();
+ }
+
+ if (save_autopoll != 0)
+ pmu_adb_autopoll(save_autopoll);
+
+ return 1;
+}
+
/* Construct and send a pmu request */
int
pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
@@ -366,7 +415,10 @@ pmu_send_request(struct adb_request *req)
req->nbytes = 5;
for (i = 1; i <= 4; ++i)
req->data[i] = req->data[i+1];
- req->reply_len = 0;
+ req->reply_len = 3;
+ req->reply[0] = CUDA_PACKET;
+ req->reply[1] = 0;
+ req->reply[2] = CUDA_SET_TIME;
return pmu_queue_request(req);
}
break;
@@ -691,6 +743,44 @@ set_volume(int level)
{
}
+void
+pmu_restart(void)
+{
+ struct adb_request req;
+
+ _disable_interrupts();
+
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+ while(!req.complete)
+ pmu_poll();
+
+ pmu_request(&req, NULL, 1, PMU_RESET);
+ while(!req.complete || (pmu_state != idle))
+ pmu_poll();
+ for (;;)
+ ;
+}
+
+void
+pmu_shutdown(void)
+{
+ struct adb_request req;
+
+ _disable_interrupts();
+
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+ while(!req.complete)
+ pmu_poll();
+
+ pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
+ 'M', 'A', 'T', 'T');
+ while(!req.complete || (pmu_state != idle))
+ pmu_poll();
+ for (;;)
+ ;
+}
+
+
#ifdef CONFIG_PMAC_PBOOK
/*
@@ -855,12 +945,14 @@ int powerbook_sleep(void)
notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
/* reenable ADB autopoll */
- pmu_adb_autopoll(1);
+ pmu_adb_autopoll(adb_dev_map);
/* Turn on the screen backlight, if it was on before */
if (save_backlight)
pmu_enable_backlight(1);
+ /* Wait for the hard disk to spin up */
+
return 0;
}