Subversion Repositories HelenOS

Rev

Rev 3528 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3528 Rev 3529
1
/*
1
/*
2
 * Copyright (c) 2007 Michal Kebrt, Petr Stepan
2
 * Copyright (c) 2007 Michal Kebrt, Petr Stepan
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup arm32qemu_icp
29
/** @addtogroup arm32qemu_icp
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 *  @brief QEMU icp drivers.
33
 *  @brief QEMU icp drivers.
34
 */
34
 */
35
 
35
 
36
#include <interrupt.h>
36
#include <interrupt.h>
37
#include <ipc/irq.h>
37
#include <ipc/irq.h>
38
#include <console/chardev.h>
38
#include <console/chardev.h>
39
#include <arch/drivers/qemu.h>
39
#include <arch/drivers/qemu.h>
40
#include <console/console.h>
40
#include <console/console.h>
41
#include <sysinfo/sysinfo.h>
41
#include <sysinfo/sysinfo.h>
42
#include <print.h>
42
#include <print.h>
43
#include <ddi/device.h>
43
#include <ddi/device.h>
44
#include <mm/page.h>
44
#include <mm/page.h>
45
#include <arch/machine.h>
45
#include <arch/machine.h>
46
#include <arch/debug/print.h>
46
#include <arch/debug/print.h>
-
 
47
#include <genarch/fb/fb.h>
-
 
48
#include <genarch/fb/visuals.h>
47
 
49
 
48
/* Addresses of devices. */
50
/* Addresses of devices. */
49
#define QEMU_ICP_VIDEORAM            0x16000000
51
#define QEMU_ICP_VIDEORAM            0x16000000
50
#define QEMU_ICP_KBD                 0x18000000
52
#define QEMU_ICP_KBD                 0x18000000
51
#define QEMU_ICP_HALT_OFFSET         0x10
53
#define QEMU_ICP_HALT_OFFSET         0x10
52
#define QEMU_ICP_RTC                 0x13000000
54
#define QEMU_ICP_RTC                 0x13000000
53
#define QEMU_ICP_RTC_FREQ_OFFSET     0x100
55
#define QEMU_ICP_RTC_FREQ_OFFSET     0x100
54
#define QEMU_ICP_RTC_ACK_OFFSET      0x110
56
#define QEMU_ICP_RTC_ACK_OFFSET      0x110
55
#define QEMU_ICP_IRQC                0x14000000
57
#define QEMU_ICP_IRQC                0x14000000
56
#define QEMU_ICP_IRQC_MASK_OFFSET    0x8
58
#define QEMU_ICP_IRQC_MASK_OFFSET    0x8
57
#define QEMU_ICP_IRQC_UNMASK_OFFSET  0xC
59
#define QEMU_ICP_IRQC_UNMASK_OFFSET  0xC
58
#define QEMU_ICP_MP                  0x11000000
60
#define QEMU_ICP_MP                  0x11000000
59
#define QEMU_ICP_MP_MEMSIZE_OFFSET   0x0090
61
#define QEMU_ICP_MP_MEMSIZE_OFFSET   0x0090
60
#define QEMU_ICP_FB                  0x94000
62
#define QEMU_ICP_FB                  0x94000
61
 
63
 
62
#define ICP_VGA              0xC0000000
64
#define ICP_VGA              0xC0000000
63
#define ICP_CMCR             0x10000000
65
#define ICP_CMCR             0x10000000
64
 
66
 
65
/* IRQs */
67
/* IRQs */
66
#define QEMU_ICP_KBD_IRQ        3
68
#define QEMU_ICP_KBD_IRQ        3
67
#define QEMU_ICP_TIMER_IRQ  5
69
#define QEMU_ICP_TIMER_IRQ  5
68
 
70
 
69
static qemu_icp_hw_map_t qemu_icp_hw_map;
71
static qemu_icp_hw_map_t qemu_icp_hw_map;
70
static chardev_t console;
72
static chardev_t console;
71
static irq_t qemu_icp_console_irq;
73
static irq_t qemu_icp_console_irq;
72
static irq_t qemu_icp_timer_irq;
74
static irq_t qemu_icp_timer_irq;
73
 
75
 
74
static bool hw_map_init_called = false;
76
static bool hw_map_init_called = false;
75
static bool vga_init = false;
77
static bool vga_init = false;
76
 
78
 
77
static void qemu_icp_kbd_enable(chardev_t *dev);
79
static void qemu_icp_kbd_enable(chardev_t *dev);
78
static void qemu_icp_kbd_disable(chardev_t *dev);
80
static void qemu_icp_kbd_disable(chardev_t *dev);
79
static void qemu_icp_write(chardev_t *dev, const char ch);
81
static void qemu_icp_write(chardev_t *dev, const char ch);
80
static char qemu_icp_do_read(chardev_t *dev);
82
static char qemu_icp_do_read(chardev_t *dev);
81
void icp_vga_init(void);
83
void icp_vga_init(void);
82
 
84
 
83
static chardev_operations_t qemu_icp_ops = {
85
static chardev_operations_t qemu_icp_ops = {
84
    .resume = qemu_icp_kbd_enable,
86
    .resume = qemu_icp_kbd_enable,
85
    .suspend = qemu_icp_kbd_disable,
87
    .suspend = qemu_icp_kbd_disable,
86
    .write = qemu_icp_write,
88
    .write = qemu_icp_write,
87
    .read = qemu_icp_do_read,
89
    .read = qemu_icp_do_read,
88
};
90
};
89
 
91
 
90
/** Initializes the vga
92
/** Initializes the vga
91
 *
93
 *
92
 */
94
 */
93
void icp_vga_init(void)
95
void icp_vga_init(void)
94
{
96
{
95
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0x14) = 0xA05F0000;
97
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0x14) = 0xA05F0000;
96
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0x1C) = 0x12C11000;
98
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0x1C) = 0x12C11000;
97
    *(uint32_t*)qemu_icp_hw_map.vga = 0x3F1F3F9C;
99
    *(uint32_t*)qemu_icp_hw_map.vga = 0x3F1F3F9C;
98
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x4) = 0x080B61DF;
100
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x4) = 0x080B61DF;
99
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x8) = 0x067F3800;
101
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x8) = 0x067F3800;
100
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x10) = QEMU_ICP_FB;
102
    *(uint32_t*)((char *)(qemu_icp_hw_map.vga) + 0x10) = QEMU_ICP_FB;
101
    *(uint32_t *)((char *)(qemu_icp_hw_map.vga) + 0x1C) = 0x182B;
103
    *(uint32_t *)((char *)(qemu_icp_hw_map.vga) + 0x1C) = 0x182B;
102
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0xC) = 0x33805000;
104
    *(uint32_t*)((char *)(qemu_icp_hw_map.cmcr)+0xC) = 0x33805000;
103
   
105
   
104
}
106
}
105
 
107
 
106
/** Returns the mask of active interrupts. */
108
/** Returns the mask of active interrupts. */
107
static inline uint32_t qemu_icp_irqc_get_sources(void)
109
static inline uint32_t qemu_icp_irqc_get_sources(void)
108
{
110
{
109
    return *((uint32_t *) qemu_icp_hw_map.irqc);
111
    return *((uint32_t *) qemu_icp_hw_map.irqc);
110
}
112
}
111
 
113
 
112
 
114
 
113
/** Masks interrupt.
115
/** Masks interrupt.
114
 *
116
 *
115
 * @param irq interrupt number
117
 * @param irq interrupt number
116
 */
118
 */
117
static inline void qemu_icp_irqc_mask(uint32_t irq)
119
static inline void qemu_icp_irqc_mask(uint32_t irq)
118
{
120
{
119
    *((uint32_t *) qemu_icp_hw_map.irqc_mask) = irq;
121
    *((uint32_t *) qemu_icp_hw_map.irqc_mask) = irq;
120
}
122
}
121
 
123
 
122
 
124
 
123
/** Unmasks interrupt.
125
/** Unmasks interrupt.
124
 *
126
 *
125
 * @param irq interrupt number
127
 * @param irq interrupt number
126
 */
128
 */
127
static inline void qemu_icp_irqc_unmask(uint32_t irq)
129
static inline void qemu_icp_irqc_unmask(uint32_t irq)
128
{
130
{
129
    *((uint32_t *) qemu_icp_hw_map.irqc_unmask) = irq;
131
    *((uint32_t *) qemu_icp_hw_map.irqc_unmask) = irq;
130
}
132
}
131
 
133
 
-
 
134
/** Initializes the icp frame buffer */
-
 
135
void qemu_icp_fb_init(void)
-
 
136
{
-
 
137
    fb_init(qemu_icp_get_fb_address(), 640, 480, 2560, VISUAL_BGR_8_8_8_0);
-
 
138
}
132
 
139
 
133
/** Initializes #qemu_icp_hw_map. */
140
/** Initializes #qemu_icp_hw_map. */
134
void qemu_icp_hw_map_init(void)
141
void qemu_icp_hw_map_init(void)
135
{
142
{
136
    qemu_icp_hw_map.videoram = hw_map(QEMU_ICP_VIDEORAM, PAGE_SIZE);
143
    qemu_icp_hw_map.videoram = hw_map(QEMU_ICP_VIDEORAM, PAGE_SIZE);
137
    qemu_icp_hw_map.kbd = hw_map(QEMU_ICP_KBD, PAGE_SIZE);
144
    qemu_icp_hw_map.kbd = hw_map(QEMU_ICP_KBD, PAGE_SIZE);
138
    qemu_icp_hw_map.rtc = hw_map(QEMU_ICP_RTC, PAGE_SIZE);
145
    qemu_icp_hw_map.rtc = hw_map(QEMU_ICP_RTC, PAGE_SIZE);
139
    qemu_icp_hw_map.irqc = hw_map(QEMU_ICP_IRQC, PAGE_SIZE);
146
    qemu_icp_hw_map.irqc = hw_map(QEMU_ICP_IRQC, PAGE_SIZE);
140
 
147
 
141
    qemu_icp_hw_map.rtc_freq = qemu_icp_hw_map.rtc + QEMU_ICP_RTC_FREQ_OFFSET;
148
    qemu_icp_hw_map.rtc_freq = qemu_icp_hw_map.rtc + QEMU_ICP_RTC_FREQ_OFFSET;
142
    qemu_icp_hw_map.rtc_ack = qemu_icp_hw_map.rtc + QEMU_ICP_RTC_ACK_OFFSET;
149
    qemu_icp_hw_map.rtc_ack = qemu_icp_hw_map.rtc + QEMU_ICP_RTC_ACK_OFFSET;
143
    qemu_icp_hw_map.irqc_mask = qemu_icp_hw_map.irqc + QEMU_ICP_IRQC_MASK_OFFSET;
150
    qemu_icp_hw_map.irqc_mask = qemu_icp_hw_map.irqc + QEMU_ICP_IRQC_MASK_OFFSET;
144
    qemu_icp_hw_map.irqc_unmask = qemu_icp_hw_map.irqc +
151
    qemu_icp_hw_map.irqc_unmask = qemu_icp_hw_map.irqc +
145
        QEMU_ICP_IRQC_UNMASK_OFFSET;
152
        QEMU_ICP_IRQC_UNMASK_OFFSET;
146
    qemu_icp_hw_map.cmcr = hw_map(ICP_CMCR, PAGE_SIZE);
153
    qemu_icp_hw_map.cmcr = hw_map(ICP_CMCR, PAGE_SIZE);
147
    qemu_icp_hw_map.vga = hw_map(ICP_VGA, PAGE_SIZE);
154
    qemu_icp_hw_map.vga = hw_map(ICP_VGA, PAGE_SIZE);
148
 
155
 
149
    //icp_vga_init();
156
    //icp_vga_init();
150
 
157
 
151
    hw_map_init_called = true;
158
    hw_map_init_called = true;
152
}
159
}
153
 
160
 
154
 
161
 
155
/** Putchar that works with qemu_icp.
162
/** Putchar that works with qemu_icp.
156
 *
163
 *
157
 * @param dev Not used.
164
 * @param dev Not used.
158
 * @param ch Characted to be printed.
165
 * @param ch Characted to be printed.
159
 */
166
 */
160
static void qemu_icp_write(chardev_t *dev, const char ch)
167
static void qemu_icp_write(chardev_t *dev, const char ch)
161
{
168
{
162
    *((char *) qemu_icp_hw_map.videoram) = ch;
169
    *((char *) qemu_icp_hw_map.videoram) = ch;
163
}
170
}
164
 
171
 
165
/** Enables qemu_icp keyboard (interrupt unmasked).
172
/** Enables qemu_icp keyboard (interrupt unmasked).
166
 *
173
 *
167
 * @param dev Not used.
174
 * @param dev Not used.
168
 *
175
 *
169
 * Called from getc().
176
 * Called from getc().
170
 */
177
 */
171
static void qemu_icp_kbd_enable(chardev_t *dev)
178
static void qemu_icp_kbd_enable(chardev_t *dev)
172
{
179
{
173
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
180
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
174
}
181
}
175
 
182
 
176
/** Disables qemu_icp keyboard (interrupt masked).
183
/** Disables qemu_icp keyboard (interrupt masked).
177
 *
184
 *
178
 * @param dev not used
185
 * @param dev not used
179
 *
186
 *
180
 * Called from getc().
187
 * Called from getc().
181
 */
188
 */
182
static void qemu_icp_kbd_disable(chardev_t *dev)
189
static void qemu_icp_kbd_disable(chardev_t *dev)
183
{
190
{
184
    qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ);
191
    qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ);
185
}
192
}
186
 
193
 
187
/** Read character using polling, assume interrupts disabled.
194
/** Read character using polling, assume interrupts disabled.
188
 *
195
 *
189
 *  @param dev Not used.
196
 *  @param dev Not used.
190
 */
197
 */
191
static char qemu_icp_do_read(chardev_t *dev)
198
static char qemu_icp_do_read(chardev_t *dev)
192
{
199
{
193
    char ch;
200
    char ch;
194
 
201
 
195
    while (1) {
202
    while (1) {
196
        ch = *((volatile char *) qemu_icp_hw_map.kbd);
203
        ch = *((volatile char *) qemu_icp_hw_map.kbd);
197
        if (ch) {
204
        if (ch) {
198
            if (ch == '\r')
205
            if (ch == '\r')
199
                return '\n';
206
                return '\n';
200
            if (ch == 0x7f)
207
            if (ch == 0x7f)
201
                return '\b';
208
                return '\b';
202
            return ch;
209
            return ch;
203
        }
210
        }
204
    }
211
    }
205
}
212
}
206
 
213
 
207
/** Process keyboard interrupt.
214
/** Process keyboard interrupt.
208
 *  
215
 *  
209
 *  @param irq IRQ information.
216
 *  @param irq IRQ information.
210
 *  @param arg Not used.
217
 *  @param arg Not used.
211
 */
218
 */
212
static void qemu_icp_irq_handler(irq_t *irq, void *arg, ...)
219
static void qemu_icp_irq_handler(irq_t *irq, void *arg, ...)
213
{
220
{
214
    if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
221
    if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
215
        ipc_irq_send_notif(irq);
222
        ipc_irq_send_notif(irq);
216
    } else {
223
    } else {
217
        char ch = 0;
224
        char ch = 0;
218
       
225
       
219
        ch = *((char *) qemu_icp_hw_map.kbd);
226
        ch = *((char *) qemu_icp_hw_map.kbd);
220
        if (ch == '\r') {
227
        if (ch == '\r') {
221
            ch = '\n';
228
            ch = '\n';
222
        }
229
        }
223
        if (ch == 0x7f) {
230
        if (ch == 0x7f) {
224
            ch = '\b';
231
            ch = '\b';
225
        }
232
        }
226
        chardev_push_character(&console, ch);
233
        chardev_push_character(&console, ch);
227
    }
234
    }
228
}
235
}
229
 
236
 
230
static irq_ownership_t qemu_icp_claim(void)
237
static irq_ownership_t qemu_icp_claim(void)
231
{
238
{
232
    return IRQ_ACCEPT;
239
    return IRQ_ACCEPT;
233
}
240
}
234
 
241
 
235
 
242
 
236
/** Acquire console back for kernel. */
243
/** Acquire console back for kernel. */
237
void qemu_icp_grab_console(void)
244
void qemu_icp_grab_console(void)
238
{
245
{
239
    ipl_t ipl = interrupts_disable();
246
    ipl_t ipl = interrupts_disable();
240
    spinlock_lock(&qemu_icp_console_irq.lock);
247
    spinlock_lock(&qemu_icp_console_irq.lock);
241
    qemu_icp_console_irq.notif_cfg.notify = false;
248
    qemu_icp_console_irq.notif_cfg.notify = false;
242
    spinlock_unlock(&qemu_icp_console_irq.lock);
249
    spinlock_unlock(&qemu_icp_console_irq.lock);
243
    interrupts_restore(ipl);
250
    interrupts_restore(ipl);
244
}
251
}
245
 
252
 
246
/** Return console to userspace. */
253
/** Return console to userspace. */
247
void qemu_icp_release_console(void)
254
void qemu_icp_release_console(void)
248
{
255
{
249
    ipl_t ipl = interrupts_disable();
256
    ipl_t ipl = interrupts_disable();
250
    spinlock_lock(&qemu_icp_console_irq.lock);
257
    spinlock_lock(&qemu_icp_console_irq.lock);
251
    if (qemu_icp_console_irq.notif_cfg.answerbox) {
258
    if (qemu_icp_console_irq.notif_cfg.answerbox) {
252
        qemu_icp_console_irq.notif_cfg.notify = true;
259
        qemu_icp_console_irq.notif_cfg.notify = true;
253
    }
260
    }
254
    spinlock_unlock(&qemu_icp_console_irq.lock);
261
    spinlock_unlock(&qemu_icp_console_irq.lock);
255
    interrupts_restore(ipl);
262
    interrupts_restore(ipl);
256
}
263
}
257
 
264
 
258
/** Initializes console object representing qemu_icp console.
265
/** Initializes console object representing qemu_icp console.
259
 *
266
 *
260
 *  @param devno device number.
267
 *  @param devno device number.
261
 */
268
 */
262
void qemu_icp_console_init(devno_t devno)
269
void qemu_icp_console_init(devno_t devno)
263
{
270
{
264
    chardev_initialize("qemu_icp_console", &console, &qemu_icp_ops);
271
    chardev_initialize("qemu_icp_console", &console, &qemu_icp_ops);
265
    stdin = &console;
272
    stdin = &console;
266
    stdout = &console;
273
    stdout = &console;
267
   
274
   
268
    irq_initialize(&qemu_icp_console_irq);
275
    irq_initialize(&qemu_icp_console_irq);
269
    qemu_icp_console_irq.devno = devno;
276
    qemu_icp_console_irq.devno = devno;
270
    qemu_icp_console_irq.inr = QEMU_ICP_KBD_IRQ;
277
    qemu_icp_console_irq.inr = QEMU_ICP_KBD_IRQ;
271
    qemu_icp_console_irq.claim = qemu_icp_claim;
278
    qemu_icp_console_irq.claim = qemu_icp_claim;
272
    qemu_icp_console_irq.handler = qemu_icp_irq_handler;
279
    qemu_icp_console_irq.handler = qemu_icp_irq_handler;
273
    irq_register(&qemu_icp_console_irq);
280
    irq_register(&qemu_icp_console_irq);
274
   
281
   
275
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
282
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
276
   
283
   
277
    sysinfo_set_item_val("kbd", NULL, true);
284
    sysinfo_set_item_val("kbd", NULL, true);
278
    sysinfo_set_item_val("kbd.devno", NULL, devno);
285
    sysinfo_set_item_val("kbd.devno", NULL, devno);
279
    sysinfo_set_item_val("kbd.inr", NULL, QEMU_ICP_KBD_IRQ);
286
    sysinfo_set_item_val("kbd.inr", NULL, QEMU_ICP_KBD_IRQ);
280
    sysinfo_set_item_val("kbd.address.virtual", NULL, qemu_icp_hw_map.kbd);
287
    sysinfo_set_item_val("kbd.address.virtual", NULL, qemu_icp_hw_map.kbd);
281
}
288
}
282
 
289
 
283
/** Starts qemu_icp Real Time Clock device, which asserts regular interrupts.
290
/** Starts qemu_icp Real Time Clock device, which asserts regular interrupts.
284
 *
291
 *
285
 * @param frequency Interrupts frequency (0 disables RTC).
292
 * @param frequency Interrupts frequency (0 disables RTC).
286
 */
293
 */
287
static void qemu_icp_timer_start(uint32_t frequency)
294
static void qemu_icp_timer_start(uint32_t frequency)
288
{
295
{
289
    *((uint32_t*) qemu_icp_hw_map.rtc_freq) = frequency;
296
    *((uint32_t*) qemu_icp_hw_map.rtc_freq) = frequency;
290
}
297
}
291
 
298
 
292
static irq_ownership_t qemu_icp_timer_claim(void)
299
static irq_ownership_t qemu_icp_timer_claim(void)
293
{
300
{
294
    return IRQ_ACCEPT;
301
    return IRQ_ACCEPT;
295
}
302
}
296
 
303
 
297
/** Timer interrupt handler.
304
/** Timer interrupt handler.
298
 *
305
 *
299
 * @param irq Interrupt information.
306
 * @param irq Interrupt information.
300
 * @param arg Not used.
307
 * @param arg Not used.
301
 */
308
 */
302
static void qemu_icp_timer_irq_handler(irq_t *irq, void *arg, ...)
309
static void qemu_icp_timer_irq_handler(irq_t *irq, void *arg, ...)
303
{
310
{
304
    /*
311
    /*
305
    * We are holding a lock which prevents preemption.
312
    * We are holding a lock which prevents preemption.
306
    * Release the lock, call clock() and reacquire the lock again.
313
    * Release the lock, call clock() and reacquire the lock again.
307
    */
314
    */
308
    spinlock_unlock(&irq->lock);
315
    spinlock_unlock(&irq->lock);
309
    clock();
316
    clock();
310
    spinlock_lock(&irq->lock);
317
    spinlock_lock(&irq->lock);
311
 
318
 
312
    /* acknowledge tick */
319
    /* acknowledge tick */
313
    *((uint32_t*) qemu_icp_hw_map.rtc_ack) = 0;
320
    *((uint32_t*) qemu_icp_hw_map.rtc_ack) = 0;
314
}
321
}
315
 
322
 
316
/** Initializes and registers timer interrupt handler. */
323
/** Initializes and registers timer interrupt handler. */
317
static void qemu_icp_timer_irq_init(void)
324
static void qemu_icp_timer_irq_init(void)
318
{
325
{
319
    irq_initialize(&qemu_icp_timer_irq);
326
    irq_initialize(&qemu_icp_timer_irq);
320
    qemu_icp_timer_irq.devno = device_assign_devno();
327
    qemu_icp_timer_irq.devno = device_assign_devno();
321
    qemu_icp_timer_irq.inr = QEMU_ICP_TIMER_IRQ;
328
    qemu_icp_timer_irq.inr = QEMU_ICP_TIMER_IRQ;
322
    qemu_icp_timer_irq.claim = qemu_icp_timer_claim;
329
    qemu_icp_timer_irq.claim = qemu_icp_timer_claim;
323
    qemu_icp_timer_irq.handler = qemu_icp_timer_irq_handler;
330
    qemu_icp_timer_irq.handler = qemu_icp_timer_irq_handler;
324
 
331
 
325
    irq_register(&qemu_icp_timer_irq);
332
    irq_register(&qemu_icp_timer_irq);
326
}
333
}
327
 
334
 
328
 
335
 
329
/** Starts timer.
336
/** Starts timer.
330
 *
337
 *
331
 * Initiates regular timer interrupts after initializing
338
 * Initiates regular timer interrupts after initializing
332
 * corresponding interrupt handler.
339
 * corresponding interrupt handler.
333
 */
340
 */
334
void qemu_icp_timer_irq_start(void)
341
void qemu_icp_timer_irq_start(void)
335
{
342
{
336
    qemu_icp_timer_irq_init();
343
    qemu_icp_timer_irq_init();
337
    qemu_icp_timer_start(QEMU_ICP_TIMER_FREQ);
344
    qemu_icp_timer_start(QEMU_ICP_TIMER_FREQ);
338
}
345
}
339
 
346
 
340
/** Returns the size of emulated memory.
347
/** Returns the size of emulated memory.
341
 *
348
 *
342
 * @return Size in bytes.
349
 * @return Size in bytes.
343
 */
350
 */
344
size_t qemu_icp_get_memory_size(void)
351
size_t qemu_icp_get_memory_size(void)
345
{
352
{
346
    //return  *((int *) (QEMU_ICP_MP + QEMU_ICP_MP_MEMSIZE_OFFSET));
353
    //return  *((int *) (QEMU_ICP_MP + QEMU_ICP_MP_MEMSIZE_OFFSET));
347
    return 0x2000000;
354
    return 0x2000000;
348
}
355
}
349
 
356
 
350
/** Prints a character.
357
/** Prints a character.
351
 *
358
 *
352
 *  @param ch Character to be printed.
359
 *  @param ch Character to be printed.
353
 */
360
 */
354
void qemu_icp_debug_putc(char ch)
361
void qemu_icp_debug_putc(char ch)
355
{
362
{
356
    char *addr = 0;
363
    char *addr = 0;
357
    if (!hw_map_init_called) {
364
    if (!hw_map_init_called) {
358
        addr = (char *) QEMU_ICP_KBD;
365
        addr = (char *) QEMU_ICP_KBD;
359
    } else {
366
    } else {
360
        addr = (char *) qemu_icp_hw_map.videoram;
367
        addr = (char *) qemu_icp_hw_map.videoram;
361
    }
368
    }
362
   
369
   
363
    if (ch == '\n')
370
    if (ch == '\n')
364
        *(addr) = '\r';
371
        *(addr) = '\r';
365
    *(addr) = ch;
372
    *(addr) = ch;
366
}
373
}
367
 
374
 
368
/** Stops qemu_icp. */
375
/** Stops qemu_icp. */
369
void qemu_icp_cpu_halt(void)
376
void qemu_icp_cpu_halt(void)
370
{
377
{
371
    char * addr = 0;
378
    char * addr = 0;
372
    if (!hw_map_init_called) {
379
    if (!hw_map_init_called) {
373
        addr = (char *) QEMU_ICP_KBD;
380
        addr = (char *) QEMU_ICP_KBD;
374
    } else {
381
    } else {
375
        addr = (char *) qemu_icp_hw_map.videoram;
382
        addr = (char *) qemu_icp_hw_map.videoram;
376
    }
383
    }
377
   
384
   
378
    *(addr + QEMU_ICP_HALT_OFFSET) = '\0';
385
    *(addr + QEMU_ICP_HALT_OFFSET) = '\0';
379
}
386
}
380
 
387
 
381
/** Gxemul specific interrupt exception handler.
388
/** Gxemul specific interrupt exception handler.
382
 *
389
 *
383
 * Determines sources of the interrupt from interrupt controller and
390
 * Determines sources of the interrupt from interrupt controller and
384
 * calls high-level handlers for them.
391
 * calls high-level handlers for them.
385
 *
392
 *
386
 * @param exc_no Interrupt exception number.
393
 * @param exc_no Interrupt exception number.
387
 * @param istate Saved processor state.
394
 * @param istate Saved processor state.
388
 */
395
 */
389
void qemu_icp_irq_exception(int exc_no, istate_t *istate)
396
void qemu_icp_irq_exception(int exc_no, istate_t *istate)
390
{
397
{
391
    uint32_t sources = qemu_icp_irqc_get_sources();
398
    uint32_t sources = qemu_icp_irqc_get_sources();
392
    int i;
399
    int i;
393
   
400
   
394
    for (i = 0; i < QEMU_ICP_IRQC_MAX_IRQ; i++) {
401
    for (i = 0; i < QEMU_ICP_IRQC_MAX_IRQ; i++) {
395
        if (sources & (1 << i)) {
402
        if (sources & (1 << i)) {
396
            irq_t *irq = irq_dispatch_and_lock(i);
403
            irq_t *irq = irq_dispatch_and_lock(i);
397
            if (irq) {
404
            if (irq) {
398
                /* The IRQ handler was found. */
405
                /* The IRQ handler was found. */
399
                irq->handler(irq, irq->arg);
406
                irq->handler(irq, irq->arg);
400
                spinlock_unlock(&irq->lock);
407
                spinlock_unlock(&irq->lock);
401
            } else {
408
            } else {
402
                /* Spurious interrupt.*/
409
                /* Spurious interrupt.*/
403
                dprintf("cpu%d: spurious interrupt (inum=%d)\n",
410
                dprintf("cpu%d: spurious interrupt (inum=%d)\n",
404
                    CPU->id, i);
411
                    CPU->id, i);
405
            }
412
            }
406
        }
413
        }
407
    }
414
    }
408
}
415
}
409
 
416
 
410
/** Returns address of framebuffer device.
417
/** Returns address of framebuffer device.
411
 *
418
 *
412
 *  @return Address of framebuffer device.
419
 *  @return Address of framebuffer device.
413
 */
420
 */
414
uintptr_t qemu_icp_get_fb_address(void)
421
uintptr_t qemu_icp_get_fb_address(void)
415
{
422
{
416
    if (!vga_init) {
423
    if (!vga_init) {
417
        icp_vga_init();
424
        icp_vga_init();
418
        vga_init = true;
425
        vga_init = true;
419
    }
426
    }
420
    return (uintptr_t) QEMU_ICP_FB;
427
    return (uintptr_t) QEMU_ICP_FB;
421
}
428
}
422
 
429
 
423
 
430
 
424
/** @}
431
/** @}
425
 */
432
 */
426
 
433