1 | /* |
---|
2 | * Heathrow PIC support (standard PowerMac PIC) |
---|
3 | * |
---|
4 | * Copyright (c) 2005 Fabrice Bellard |
---|
5 | * |
---|
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
7 | * of this software and associated documentation files (the "Software"), to deal |
---|
8 | * in the Software without restriction, including without limitation the rights |
---|
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
10 | * copies of the Software, and to permit persons to whom the Software is |
---|
11 | * furnished to do so, subject to the following conditions: |
---|
12 | * |
---|
13 | * The above copyright notice and this permission notice shall be included in |
---|
14 | * all copies or substantial portions of the Software. |
---|
15 | * |
---|
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
---|
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
---|
22 | * THE SOFTWARE. |
---|
23 | */ |
---|
24 | #include "vl.h" |
---|
25 | |
---|
26 | //#define DEBUG |
---|
27 | |
---|
28 | typedef struct HeathrowPIC { |
---|
29 | uint32_t events; |
---|
30 | uint32_t mask; |
---|
31 | uint32_t levels; |
---|
32 | uint32_t level_triggered; |
---|
33 | } HeathrowPIC; |
---|
34 | |
---|
35 | struct HeathrowPICS { |
---|
36 | HeathrowPIC pics[2]; |
---|
37 | }; |
---|
38 | |
---|
39 | static inline int check_irq(HeathrowPIC *pic) |
---|
40 | { |
---|
41 | return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask; |
---|
42 | } |
---|
43 | |
---|
44 | /* update the CPU irq state */ |
---|
45 | static void heathrow_pic_update(HeathrowPICS *s) |
---|
46 | { |
---|
47 | if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) { |
---|
48 | cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD); |
---|
49 | } else { |
---|
50 | cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD); |
---|
51 | } |
---|
52 | } |
---|
53 | |
---|
54 | static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
---|
55 | { |
---|
56 | HeathrowPICS *s = opaque; |
---|
57 | HeathrowPIC *pic; |
---|
58 | unsigned int n; |
---|
59 | |
---|
60 | value = bswap32(value); |
---|
61 | #ifdef DEBUG |
---|
62 | printf("pic_writel: %08x: %08x\n", |
---|
63 | addr, value); |
---|
64 | #endif |
---|
65 | n = ((addr & 0xfff) - 0x10) >> 4; |
---|
66 | if (n >= 2) |
---|
67 | return; |
---|
68 | pic = &s->pics[n]; |
---|
69 | switch(addr & 0xf) { |
---|
70 | case 0x04: |
---|
71 | pic->mask = value; |
---|
72 | heathrow_pic_update(s); |
---|
73 | break; |
---|
74 | case 0x08: |
---|
75 | /* do not reset level triggered IRQs */ |
---|
76 | value &= ~pic->level_triggered; |
---|
77 | pic->events &= ~value; |
---|
78 | heathrow_pic_update(s); |
---|
79 | break; |
---|
80 | default: |
---|
81 | break; |
---|
82 | } |
---|
83 | } |
---|
84 | |
---|
85 | static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) |
---|
86 | { |
---|
87 | HeathrowPICS *s = opaque; |
---|
88 | HeathrowPIC *pic; |
---|
89 | unsigned int n; |
---|
90 | uint32_t value; |
---|
91 | |
---|
92 | n = ((addr & 0xfff) - 0x10) >> 4; |
---|
93 | if (n >= 2) { |
---|
94 | value = 0; |
---|
95 | } else { |
---|
96 | pic = &s->pics[n]; |
---|
97 | switch(addr & 0xf) { |
---|
98 | case 0x0: |
---|
99 | value = pic->events; |
---|
100 | break; |
---|
101 | case 0x4: |
---|
102 | value = pic->mask; |
---|
103 | break; |
---|
104 | case 0xc: |
---|
105 | value = pic->levels; |
---|
106 | break; |
---|
107 | default: |
---|
108 | value = 0; |
---|
109 | break; |
---|
110 | } |
---|
111 | } |
---|
112 | #ifdef DEBUG |
---|
113 | printf("pic_readl: %08x: %08x\n", |
---|
114 | addr, value); |
---|
115 | #endif |
---|
116 | value = bswap32(value); |
---|
117 | return value; |
---|
118 | } |
---|
119 | |
---|
120 | static CPUWriteMemoryFunc *pic_write[] = { |
---|
121 | &pic_writel, |
---|
122 | &pic_writel, |
---|
123 | &pic_writel, |
---|
124 | }; |
---|
125 | |
---|
126 | static CPUReadMemoryFunc *pic_read[] = { |
---|
127 | &pic_readl, |
---|
128 | &pic_readl, |
---|
129 | &pic_readl, |
---|
130 | }; |
---|
131 | |
---|
132 | |
---|
133 | void heathrow_pic_set_irq(void *opaque, int num, int level) |
---|
134 | { |
---|
135 | HeathrowPICS *s = opaque; |
---|
136 | HeathrowPIC *pic; |
---|
137 | unsigned int irq_bit; |
---|
138 | |
---|
139 | #if defined(DEBUG) |
---|
140 | { |
---|
141 | static int last_level[64]; |
---|
142 | if (last_level[num] != level) { |
---|
143 | printf("set_irq: num=0x%02x level=%d\n", num, level); |
---|
144 | last_level[num] = level; |
---|
145 | } |
---|
146 | } |
---|
147 | #endif |
---|
148 | pic = &s->pics[1 - (num >> 5)]; |
---|
149 | irq_bit = 1 << (num & 0x1f); |
---|
150 | if (level) { |
---|
151 | pic->events |= irq_bit & ~pic->level_triggered; |
---|
152 | pic->levels |= irq_bit; |
---|
153 | } else { |
---|
154 | pic->levels &= ~irq_bit; |
---|
155 | } |
---|
156 | heathrow_pic_update(s); |
---|
157 | } |
---|
158 | |
---|
159 | HeathrowPICS *heathrow_pic_init(int *pmem_index) |
---|
160 | { |
---|
161 | HeathrowPICS *s; |
---|
162 | |
---|
163 | s = qemu_mallocz(sizeof(HeathrowPICS)); |
---|
164 | s->pics[0].level_triggered = 0; |
---|
165 | s->pics[1].level_triggered = 0x1ff00000; |
---|
166 | *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s); |
---|
167 | return s; |
---|
168 | } |
---|