Subversion Repositories HelenOS

Rev

Rev 2307 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
982 decky 1
/*
2071 jermar 2
 * Copyright (c) 2006 Martin Decky
982 decky 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
 
1734 decky 29
/** @addtogroup ppc32  
1702 cejka 30
 * @{
31
 */
32
/** @file
33
 */
34
 
982 decky 35
#include <arch/drivers/cuda.h>
2089 decky 36
#include <ipc/irq.h>
982 decky 37
#include <arch/asm.h>
987 decky 38
#include <console/console.h>
1628 decky 39
#include <console/chardev.h>
1480 palkovsky 40
#include <arch/drivers/pic.h>
1625 decky 41
#include <sysinfo/sysinfo.h>
1480 palkovsky 42
#include <interrupt.h>
1619 decky 43
#include <stdarg.h>
2456 hudecek 44
#include <synch/rcu.h>
982 decky 45
 
1928 decky 46
#define CUDA_IRQ 10
1633 decky 47
#define SPECIAL     '?'
48
 
1619 decky 49
#define PACKET_ADB  0x00
50
#define PACKET_CUDA 0x01
51
 
2307 hudecek 52
#define CUDA_POWERDOWN  0x0a
53
#define CUDA_RESET      0x11
982 decky 54
 
55
#define RS 0x200
56
#define B (0 * RS)
57
#define A (1 * RS)
58
#define SR (10 * RS)
59
#define ACR (11 * RS)
60
 
61
#define SR_OUT 0x10
62
#define TACK 0x10
63
#define TIP 0x20
64
 
65
 
1780 jermar 66
static volatile uint8_t *cuda = NULL;
1928 decky 67
static irq_t cuda_irq;      /**< Cuda's IRQ. */
982 decky 68
 
1619 decky 69
static char lchars[0x80] = {
1633 decky 70
    'a',
71
    's',
72
    'd',
73
    'f',
74
    'h',
75
    'g',
76
    'z',
77
    'x',
78
    'c',
79
    'v',
80
    SPECIAL,
81
    'b',
82
    'q',
83
    'w',
84
    'e',
85
    'r',
86
    'y',
87
    't',
88
    '1',
89
    '2',
90
    '3',
91
    '4',
92
    '6',
93
    '5',
94
    '=',
95
    '9',
96
    '7',
97
    '-',
98
    '8',
99
    '0',
100
    ']',
101
    'o',
102
    'u',
103
    '[',
104
    'i',
105
    'p',
106
    '\n',    /* Enter */
107
    'l',
108
    'j',
109
    '\'',
110
    'k',
111
    ';',
112
    '\\',
113
    ',',
114
    '/',
115
    'n',
116
    'm',
117
    '.',
118
    '\t',    /* Tab */
119
    ' ',
120
    '`',
121
    '\b',    /* Backspace */
122
    SPECIAL,
123
    SPECIAL, /* Escape */
124
    SPECIAL, /* Ctrl */
125
    SPECIAL, /* Alt */
126
    SPECIAL, /* Shift */
127
    SPECIAL, /* Caps-Lock */
128
    SPECIAL, /* RAlt */
129
    SPECIAL, /* Left */
130
    SPECIAL, /* Right */
131
    SPECIAL, /* Down */
132
    SPECIAL, /* Up */
133
    SPECIAL,
134
    SPECIAL,
135
    '.',     /* Keypad . */
136
    SPECIAL,
137
    '*',     /* Keypad * */
138
    SPECIAL,
139
    '+',     /* Keypad + */
140
    SPECIAL,
141
    SPECIAL, /* NumLock */
142
    SPECIAL,
143
    SPECIAL,
144
    SPECIAL,
145
    '/',     /* Keypad / */
146
    '\n',    /* Keypad Enter */
147
    SPECIAL,
148
    '-',     /* Keypad - */
149
    SPECIAL,
150
    SPECIAL,
151
    SPECIAL,
152
    '0',     /* Keypad 0 */
153
    '1',     /* Keypad 1 */
154
    '2',     /* Keypad 2 */
155
    '3',     /* Keypad 3 */
156
    '4',     /* Keypad 4 */
157
    '5',     /* Keypad 5 */
158
    '6',     /* Keypad 6 */
159
    '7',     /* Keypad 7 */
160
    SPECIAL,
161
    '8',     /* Keypad 8 */
162
    '9',     /* Keypad 9 */
163
    SPECIAL,
164
    SPECIAL,
165
    SPECIAL,
166
    SPECIAL, /* F5 */
167
    SPECIAL, /* F6 */
168
    SPECIAL, /* F7 */
169
    SPECIAL, /* F3 */
170
    SPECIAL, /* F8 */
171
    SPECIAL, /* F9 */
172
    SPECIAL,
173
    SPECIAL, /* F11 */
174
    SPECIAL,
175
    SPECIAL, /* F13 */
176
    SPECIAL,
177
    SPECIAL, /* ScrollLock */
178
    SPECIAL,
179
    SPECIAL, /* F10 */
180
    SPECIAL,
181
    SPECIAL, /* F12 */
182
    SPECIAL,
183
    SPECIAL, /* Pause */
184
    SPECIAL, /* Insert */
185
    SPECIAL, /* Home */
186
    SPECIAL, /* PageUp */
187
    SPECIAL, /* Delete */
188
    SPECIAL, /* F4 */
189
    SPECIAL, /* End */
190
    SPECIAL, /* F2 */
191
    SPECIAL, /* PageDown */
192
    SPECIAL  /* F1 */
1619 decky 193
};
194
 
195
 
1780 jermar 196
static void receive_packet(uint8_t *kind, index_t count, uint8_t data[])
1619 decky 197
{
198
    cuda[B] = cuda[B] & ~TIP;
199
    *kind = cuda[SR];
200
 
201
    index_t i;
202
    for (i = 0; i < count; i++)
203
        data[i] = cuda[SR];
204
 
205
    cuda[B] = cuda[B] | TIP;
206
}
207
 
208
 
1606 decky 209
/* Called from getc(). */
210
static void cuda_resume(chardev_t *d)
211
{
212
}
213
 
214
 
215
/* Called from getc(). */
216
static void cuda_suspend(chardev_t *d)
217
{
218
}
219
 
220
 
221
static char key_read(chardev_t *d)
222
{
223
    char ch;
224
 
225
    ch = 0;
226
    return ch;
227
}
228
 
229
 
1628 decky 230
static chardev_t kbrd;
1606 decky 231
static chardev_operations_t ops = {
232
    .suspend = cuda_suspend,
233
    .resume = cuda_resume,
234
    .read = key_read
235
};
236
 
1619 decky 237
 
1633 decky 238
int cuda_get_scancode(void)
1480 palkovsky 239
{
1780 jermar 240
    uint8_t kind;
241
    uint8_t data[4];
1619 decky 242
 
243
    receive_packet(&kind, 4, data);
244
 
1628 decky 245
    if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c))
246
        return data[2];
247
 
1633 decky 248
    return -1;
1480 palkovsky 249
}
982 decky 250
 
1928 decky 251
static void cuda_irq_handler(irq_t *irq, void *arg, ...)
1628 decky 252
{
2456 hudecek 253
    if ((rcu_dereference_pointer(irq->notif_cfg).notify) && (rcu_dereference_pointer(irq->notif_cfg).answerbox))
1928 decky 254
        ipc_irq_send_notif(irq);
255
    else {
256
        int scan_code = cuda_get_scancode();
257
 
258
        if (scan_code != -1) {
259
            uint8_t scancode = (uint8_t) scan_code;
260
            if ((scancode & 0x80) != 0x80)
261
                chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
262
        }
1633 decky 263
    }
1628 decky 264
}
265
 
1928 decky 266
static irq_ownership_t cuda_claim(void)
267
{
268
    return IRQ_ACCEPT;
269
}
1628 decky 270
 
1928 decky 271
 
1734 decky 272
/** Initialize keyboard and service interrupts using kernel routine */
273
void cuda_grab(void)
274
{
1944 jermar 275
    ipl_t ipl = interrupts_disable();
2456 hudecek 276
    //rcu_read_lock() is not needed, ints are disabled
277
    //rcu: atomic update doesn't need reallocation
278
    rcu_dereference_pointer(cuda_irq.notif_cfg).notify = false;
1944 jermar 279
    interrupts_restore(ipl);
1734 decky 280
}
281
 
282
 
283
/** Resume the former interrupt vector */
284
void cuda_release(void)
285
{
1944 jermar 286
    ipl_t ipl = interrupts_disable();
2456 hudecek 287
    //rcu: atomic update doesn't need reallocation
1944 jermar 288
    spinlock_lock(&cuda_irq.lock);
2456 hudecek 289
    if (rcu_dereference_pointer(cuda_irq.notif_cfg).answerbox)
290
        rcu_dereference_pointer(cuda_irq.notif_cfg).notify = true;
1944 jermar 291
    spinlock_unlock(&cuda_irq.unlock);
292
    interrupts_restore(ipl);
1734 decky 293
}
294
 
295
 
1928 decky 296
void cuda_init(devno_t devno, uintptr_t base, size_t size)
990 decky 297
{
1928 decky 298
    cuda = (uint8_t *) hw_map(base, size); 
1619 decky 299
 
1606 decky 300
    chardev_initialize("cuda_kbd", &kbrd, &ops);
301
    stdin = &kbrd;
1625 decky 302
 
1928 decky 303
    irq_initialize(&cuda_irq);
304
    cuda_irq.devno = devno;
305
    cuda_irq.inr = CUDA_IRQ;
306
    cuda_irq.claim = cuda_claim;
307
    cuda_irq.handler = cuda_irq_handler;
308
    irq_register(&cuda_irq);
309
 
310
    pic_enable_interrupt(CUDA_IRQ);
311
 
312
    sysinfo_set_item_val("kbd", NULL, true);
313
    sysinfo_set_item_val("kbd.devno", NULL, devno);
314
    sysinfo_set_item_val("kbd.inr", NULL, CUDA_IRQ);
315
    sysinfo_set_item_val("kbd.address.virtual", NULL, base);
990 decky 316
}
317
 
318
 
2307 hudecek 319
static void send_packet(const uint8_t kind, count_t count, ...)
1628 decky 320
{
321
    index_t i;
322
    va_list va;
323
 
324
    cuda[B] = cuda[B] | TIP;
325
    cuda[ACR] = cuda[ACR] | SR_OUT;
326
    cuda[SR] = kind;
327
    cuda[B] = cuda[B] & ~TIP;
328
 
329
    va_start(va, count);
330
 
331
    for (i = 0; i < count; i++) {
332
        cuda[ACR] = cuda[ACR] | SR_OUT;
333
        cuda[SR] = va_arg(va, int);
334
        cuda[B] = cuda[B] | TACK;
335
    }
336
 
337
    va_end(va);
338
 
339
    cuda[B] = cuda[B] | TIP;
340
}
341
 
342
 
982 decky 343
void cpu_halt(void) {
1269 decky 344
    asm volatile (
345
        "b 0\n"
346
    );
982 decky 347
}
1702 cejka 348
 
2307 hudecek 349
void arch_reboot(void) {
350
    send_packet(PACKET_CUDA, 1, CUDA_RESET);
351
    asm volatile (
352
        "b 0\n"
353
    );
354
}
355
 
1734 decky 356
/** @}
1702 cejka 357
 */