summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac/baboon.c
blob: 8ea7498cec3729d5c699fccbadf3fbd835380a7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Baboon Custom IC Management
 *
 * 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;

irqreturn_t baboon_irq(int, void *);

#if 0
extern int macide_ack_intr(struct ata_channel *);
#endif

/*
 * 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.
 */

irqreturn_t baboon_irq(int irq, void *dev_id)
{
	int irq_bit, irq_num;
	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 IRQ_NONE;

	irq_num = IRQ_BABOON_0;
	irq_bit = 1;
	do {
	        if (events & irq_bit/* & baboon_active*/) {
			baboon_active &= ~irq_bit;
			baboon->mb_ifr &= ~irq_bit;
			m68k_handle_int(irq_num);
			baboon_active |= irq_bit;
		}
		irq_bit <<= 1;
		irq_num++;
	} while(events >= 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
	return IRQ_HANDLED;
}

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);
}