~galfy/helenos/bird-port-mainline

« back to all changes in this revision

Viewing changes to kernel/arch/ia64/src/ia64.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005 Jakub Jermar
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * - Redistributions of source code must retain the above copyright
 
10
 *   notice, this list of conditions and the following disclaimer.
 
11
 * - Redistributions in binary form must reproduce the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer in the
 
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
 
15
 *   derived from this software without specific prior written permission.
 
16
 *
 
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
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
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
 
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
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/** @addtogroup ia64
 
30
 * @{
 
31
 */
 
32
/** @file
 
33
 */
 
34
 
 
35
#include <arch.h>
 
36
#include <arch/drivers/ski.h>
 
37
#include <arch/drivers/it.h>
 
38
#include <arch/interrupt.h>
 
39
#include <arch/barrier.h>
 
40
#include <arch/asm.h>
 
41
#include <arch/register.h>
 
42
#include <arch/types.h>
 
43
#include <arch/context.h>
 
44
#include <arch/stack.h>
 
45
#include <arch/mm/page.h>
 
46
#include <mm/as.h>
 
47
#include <config.h>
 
48
#include <userspace.h>
 
49
#include <console/console.h>
 
50
#include <proc/uarg.h>
 
51
#include <syscall/syscall.h>
 
52
#include <ddi/irq.h>
 
53
#include <arch/bootinfo.h>
 
54
#include <genarch/drivers/legacy/ia32/io.h>
 
55
#include <genarch/drivers/ega/ega.h>
 
56
#include <genarch/kbrd/kbrd.h>
 
57
#include <genarch/srln/srln.h>
 
58
#include <genarch/drivers/i8042/i8042.h>
 
59
#include <genarch/drivers/ns16550/ns16550.h>
 
60
#include <arch/drivers/kbd.h>
 
61
#include <smp/smp.h>
 
62
#include <smp/ipi.h>
 
63
#include <arch/atomic.h>
 
64
#include <panic.h>
 
65
#include <print.h>
 
66
#include <sysinfo/sysinfo.h>
 
67
#include <string.h>
 
68
 
 
69
/* NS16550 as a COM 1 */
 
70
#define NS16550_IRQ  (4 + LEGACY_INTERRUPT_BASE)
 
71
 
 
72
bootinfo_t *bootinfo;
 
73
 
 
74
static uint64_t iosapic_base = 0xfec00000;
 
75
 
 
76
/** Performs ia64-specific initialization before main_bsp() is called. */
 
77
void arch_pre_main(void)
 
78
{
 
79
        /* Setup usermode init tasks. */
 
80
 
 
81
        unsigned int i;
 
82
        
 
83
        init.cnt = bootinfo->taskmap.count;
 
84
        
 
85
        for (i = 0; i < init.cnt; i++) {
 
86
                init.tasks[i].addr =
 
87
                    ((unsigned long) bootinfo->taskmap.tasks[i].addr) |
 
88
                    VRN_MASK;
 
89
                init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
 
90
                str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
 
91
                    bootinfo->taskmap.tasks[i].name);
 
92
        }
 
93
}
 
94
 
 
95
void arch_pre_mm_init(void)
 
96
{
 
97
        /*
 
98
         * Set Interruption Vector Address (i.e. location of interruption vector
 
99
         * table).
 
100
         */
 
101
        iva_write((uintptr_t) &ivt);
 
102
        srlz_d();
 
103
        
 
104
}
 
105
 
 
106
static void iosapic_init(void)
 
107
{
 
108
        uint64_t IOSAPIC = PA2KA((unative_t)(iosapic_base)) | FW_OFFSET;
 
109
        int i;
 
110
        
 
111
        int myid, myeid;
 
112
        
 
113
        myid = ia64_get_cpu_id();
 
114
        myeid = ia64_get_cpu_eid();
 
115
 
 
116
        for (i = 0; i < 16; i++) { 
 
117
                if (i == 2)
 
118
                        continue;        /* Disable Cascade interrupt */
 
119
                ((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i;
 
120
                srlz_d();
 
121
                ((uint32_t *)(IOSAPIC + 0x10))[0] = LEGACY_INTERRUPT_BASE + i;
 
122
                srlz_d();
 
123
                ((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i + 1;
 
124
                srlz_d();
 
125
                ((uint32_t *)(IOSAPIC + 0x10))[0] = myid << (56 - 32) |
 
126
                    myeid << (48 - 32);
 
127
                srlz_d();
 
128
        }
 
129
 
 
130
}
 
131
 
 
132
void arch_post_mm_init(void)
 
133
{
 
134
        if (config.cpu_active == 1) {
 
135
                iosapic_init();
 
136
                irq_init(INR_COUNT, INR_COUNT);
 
137
        }
 
138
        it_init();      
 
139
}
 
140
 
 
141
void arch_post_cpu_init(void)
 
142
{
 
143
}
 
144
 
 
145
void arch_pre_smp_init(void)
 
146
{
 
147
}
 
148
 
 
149
void arch_post_smp_init(void)
 
150
{
 
151
#ifdef MACHINE_ski
 
152
        ski_instance_t *ski_instance = skiin_init();
 
153
        if (ski_instance) {
 
154
                srln_instance_t *srln_instance = srln_init();
 
155
                if (srln_instance) {
 
156
                        indev_t *sink = stdin_wire();
 
157
                        indev_t *srln = srln_wire(srln_instance, sink);
 
158
                        skiin_wire(ski_instance, srln);
 
159
                }
 
160
        }
 
161
        
 
162
        skiout_init();
 
163
#endif
 
164
        
 
165
#ifdef CONFIG_EGA
 
166
        ega_init(EGA_BASE, EGA_VIDEORAM);
 
167
#endif
 
168
        
 
169
#ifdef CONFIG_NS16550
 
170
        ns16550_instance_t *ns16550_instance
 
171
            = ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL);
 
172
        if (ns16550_instance) {
 
173
                srln_instance_t *srln_instance = srln_init();
 
174
                if (srln_instance) {
 
175
                        indev_t *sink = stdin_wire();
 
176
                        indev_t *srln = srln_wire(srln_instance, sink);
 
177
                        ns16550_wire(ns16550_instance, srln);
 
178
                }
 
179
        }
 
180
        
 
181
        sysinfo_set_item_val("kbd", NULL, true);
 
182
        sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ);
 
183
        sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
 
184
        sysinfo_set_item_val("kbd.address.physical", NULL,
 
185
            (uintptr_t) NS16550_BASE);
 
186
        sysinfo_set_item_val("kbd.address.kernel", NULL,
 
187
            (uintptr_t) NS16550_BASE);
 
188
#endif
 
189
        
 
190
#ifdef CONFIG_I8042
 
191
        i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
 
192
        if (i8042_instance) {
 
193
                kbrd_instance_t *kbrd_instance = kbrd_init();
 
194
                if (kbrd_instance) {
 
195
                        indev_t *sink = stdin_wire();
 
196
                        indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
 
197
                        i8042_wire(i8042_instance, kbrd);
 
198
                }
 
199
        }
 
200
        
 
201
        sysinfo_set_item_val("kbd", NULL, true);
 
202
        sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
 
203
        sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY);
 
204
        sysinfo_set_item_val("kbd.address.physical", NULL,
 
205
            (uintptr_t) I8042_BASE);
 
206
        sysinfo_set_item_val("kbd.address.kernel", NULL,
 
207
            (uintptr_t) I8042_BASE);
 
208
#endif
 
209
        
 
210
        sysinfo_set_item_val("ia64_iospace", NULL, true);
 
211
        sysinfo_set_item_val("ia64_iospace.address", NULL, true);
 
212
        sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, IO_OFFSET);
 
213
}
 
214
 
 
215
 
 
216
/** Enter userspace and never return. */
 
217
void userspace(uspace_arg_t *kernel_uarg)
 
218
{
 
219
        psr_t psr;
 
220
        rsc_t rsc;
 
221
 
 
222
        psr.value = psr_read();
 
223
        psr.cpl = PL_USER;
 
224
        psr.i = true;                   /* start with interrupts enabled */
 
225
        psr.ic = true;
 
226
        psr.ri = 0;                     /* start with instruction #0 */
 
227
        psr.bn = 1;                     /* start in bank 0 */
 
228
 
 
229
        asm volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value));
 
230
        rsc.loadrs = 0;
 
231
        rsc.be = false;
 
232
        rsc.pl = PL_USER;
 
233
        rsc.mode = 3;                   /* eager mode */
 
234
 
 
235
        switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
 
236
            ((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE -
 
237
            ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
 
238
            ((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE,
 
239
            (uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value);
 
240
 
 
241
        while (1)
 
242
                ;
 
243
}
 
244
 
 
245
/** Set thread-local-storage pointer.
 
246
 *
 
247
 * We use r13 (a.k.a. tp) for this purpose.
 
248
 */
 
249
unative_t sys_tls_set(unative_t addr)
 
250
{
 
251
        return 0;
 
252
}
 
253
 
 
254
/** Acquire console back for kernel
 
255
 *
 
256
 */
 
257
void arch_grab_console(void)
 
258
{
 
259
#ifdef MACHINE_ski
 
260
        ski_kbd_grab();
 
261
#endif
 
262
}
 
263
 
 
264
/** Return console to userspace
 
265
 *
 
266
 */
 
267
void arch_release_console(void)
 
268
{
 
269
#ifdef MACHINE_ski
 
270
        ski_kbd_release();
 
271
#endif
 
272
}
 
273
 
 
274
void arch_reboot(void)
 
275
{
 
276
        pio_write_8((ioport8_t *)0x64, 0xfe);
 
277
        while (1)
 
278
                ;
 
279
}
 
280
 
 
281
/** Construct function pointer
 
282
 *
 
283
 * @param fptr   function pointer structure
 
284
 * @param addr   function address
 
285
 * @param caller calling function address
 
286
 *
 
287
 * @return address of the function pointer
 
288
 *
 
289
 */
 
290
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
 
291
{
 
292
        fptr->fnc = (unative_t) addr;
 
293
        fptr->gp = ((unative_t *) caller)[1];
 
294
        
 
295
        return (void *) fptr;
 
296
}
 
297
 
 
298
/** @}
 
299
 */