Subversion Repositories HelenOS

Rev

Rev 4011 | Rev 4071 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4011 Rev 4070
Line 32... Line 32...
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   SGCN driver.
34
 * @brief   SGCN driver.
35
 */
35
 */
36
 
36
 
-
 
37
#include <arch.h>
37
#include <arch/drivers/sgcn.h>
38
#include <arch/drivers/sgcn.h>
38
#include <arch/drivers/kbd.h>
39
#include <arch/drivers/kbd.h>
39
#include <genarch/ofw/ofw_tree.h>
40
#include <genarch/ofw/ofw_tree.h>
40
#include <debug.h>
41
#include <debug.h>
41
#include <string.h>
42
#include <string.h>
42
#include <print.h>
43
#include <print.h>
43
#include <mm/page.h>
44
#include <mm/page.h>
44
#include <ipc/irq.h>
45
#include <proc/thread.h>
45
#include <ddi/ddi.h>
-
 
46
#include <ddi/device.h>
-
 
47
#include <console/chardev.h>
46
#include <console/chardev.h>
48
#include <console/console.h>
47
#include <console/console.h>
49
#include <ddi/device.h>
-
 
50
#include <sysinfo/sysinfo.h>
48
#include <sysinfo/sysinfo.h>
51
#include <synch/spinlock.h>
49
#include <synch/spinlock.h>
52
 
50
 
-
 
51
#define POLL_INTERVAL       10000
-
 
52
 
53
/*
53
/*
54
 * Physical address at which the SBBC starts. This value has been obtained
54
 * Physical address at which the SBBC starts. This value has been obtained
55
 * by inspecting (using Simics) memory accesses made by OBP. It is valid
55
 * by inspecting (using Simics) memory accesses made by OBP. It is valid
56
 * for the Simics-simulated Serengeti machine. The author of this code is
56
 * for the Simics-simulated Serengeti machine. The author of this code is
57
 * not sure whether this value is valid generally.
57
 * not sure whether this value is valid generally.
Line 80... Line 80...
80
#define CONSOLE_KEY     "OBPCONS"
80
#define CONSOLE_KEY     "OBPCONS"
81
 
81
 
82
/* magic string contained at the beginning of the console buffer */
82
/* magic string contained at the beginning of the console buffer */
83
#define SGCN_BUFFER_MAGIC   "CON"
83
#define SGCN_BUFFER_MAGIC   "CON"
84
 
84
 
85
/**
-
 
86
 * The driver is polling based, but in order to notify the userspace
-
 
87
 * of a key being pressed, we need to supply the interface with some
-
 
88
 * interrupt number. The interrupt number can be arbitrary as it it
-
 
89
 * will never be used for identifying HW interrupts, but only in
-
 
90
 * notifying the userspace.
-
 
91
 */
-
 
92
#define FICTIONAL_INR       1
-
 
93
 
-
 
94
 
-
 
95
/*
85
/*
96
 * Returns a pointer to the object of a given type which is placed at the given
86
 * Returns a pointer to the object of a given type which is placed at the given
97
 * offset from the SRAM beginning.
87
 * offset from the SRAM beginning.
98
 */
88
 */
99
#define SRAM(type, offset)  ((type *) (sram_begin + (offset)))
89
#define SRAM(type, offset)  ((type *) (sram_begin + (offset)))
Line 121... Line 111...
121
 * starting address of the SGCN buffer, will be set by the
111
 * starting address of the SGCN buffer, will be set by the
122
 * init_sgcn_buffer_begin function
112
 * init_sgcn_buffer_begin function
123
 */
113
 */
124
static uintptr_t sgcn_buffer_begin;
114
static uintptr_t sgcn_buffer_begin;
125
 
115
 
126
/**
-
 
127
 * SGCN IRQ structure. So far used only for notifying the userspace of the
116
/* true iff the kernel driver should ignore pressed keys */
128
 * key being pressed, not for kernel being informed about keyboard interrupts.
-
 
129
 */
-
 
130
static irq_t sgcn_irq;
117
static bool kbd_disabled;
131
 
-
 
132
// TODO think of a way how to synchronize accesses to SGCN buffer between the kernel and the userspace
-
 
133
 
118
 
134
/*
119
/*
135
 * Ensures that writing to the buffer and consequent update of the write pointer
120
 * Ensures that writing to the buffer and consequent update of the write pointer
136
 * are together one atomic operation.
121
 * are together one atomic operation.
137
 */
122
 */
Line 306... Line 291...
306
{
291
{
307
    return (char) 0;
292
    return (char) 0;
308
}
293
}
309
 
294
 
310
/**
295
/**
311
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
312
 */
-
 
313
static irq_ownership_t sgcn_claim(irq_t *irq)
-
 
314
{
-
 
315
    return IRQ_DECLINE;
-
 
316
}
-
 
317
 
-
 
318
/**
-
 
319
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
320
 */
-
 
321
static void sgcn_irq_handler(irq_t *irq)
-
 
322
{
-
 
323
    panic("Not yet implemented, SGCN works in polled mode.");
-
 
324
}
-
 
325
 
-
 
326
/**
-
 
327
 * Grabs the input for kernel.
296
 * Grabs the input for kernel.
328
 */
297
 */
329
void sgcn_grab(void)
298
void sgcn_grab(void)
330
{
299
{
331
    ipl_t ipl = interrupts_disable();
-
 
332
   
-
 
333
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-
 
334
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-
 
335
   
-
 
336
    /* skip all the user typed before the grab and hasn't been processed */
-
 
337
    spinlock_lock(&sgcn_input_lock);
-
 
338
    *in_rdptr_ptr = *in_wrptr_ptr;
300
    kbd_disabled = true;
339
    spinlock_unlock(&sgcn_input_lock);
-
 
340
 
-
 
341
    spinlock_lock(&sgcn_irq.lock);
-
 
342
    sgcn_irq.notif_cfg.notify = false;
-
 
343
    spinlock_unlock(&sgcn_irq.lock);
-
 
344
   
-
 
345
    interrupts_restore(ipl);
-
 
346
}
301
}
347
 
302
 
348
/**
303
/**
349
 * Releases the input so that userspace can use it.
304
 * Releases the input so that userspace can use it.
350
 */
305
 */
351
void sgcn_release(void)
306
void sgcn_release(void)
352
{
307
{
353
    ipl_t ipl = interrupts_disable();
-
 
354
    spinlock_lock(&sgcn_irq.lock);
-
 
355
    if (sgcn_irq.notif_cfg.answerbox)
-
 
356
        sgcn_irq.notif_cfg.notify = true;
308
    kbd_disabled = true;
357
    spinlock_unlock(&sgcn_irq.lock);
-
 
358
    interrupts_restore(ipl);
-
 
359
}
309
}
360
 
310
 
361
/**
311
/**
362
 * Function regularly called by the keyboard polling thread. Finds out whether
312
 * Function regularly called by the keyboard polling thread. Finds out whether
363
 * there are some unread characters in the input queue. If so, it picks them up
313
 * there are some unread characters in the input queue. If so, it picks them up
364
 * and sends them to the upper layers of HelenOS.
314
 * and sends them to the upper layers of HelenOS.
365
 */
315
 */
366
void sgcn_poll(void)
316
static void sgcn_poll()
367
{
317
{
368
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
318
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
369
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
319
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
370
    uint32_t size = end - begin;
320
    uint32_t size = end - begin;
371
   
321
 
372
    spinlock_lock(&sgcn_input_lock);
322
    spinlock_lock(&sgcn_input_lock);
373
   
323
   
374
    ipl_t ipl = interrupts_disable();
324
    ipl_t ipl = interrupts_disable();
-
 
325
 
-
 
326
    if (kbd_disabled) {
375
    spinlock_lock(&sgcn_irq.lock);
327
        interrupts_restore(ipl);
-
 
328
        return;
-
 
329
    }
376
   
330
   
377
    /* we need pointers to volatile variables */
331
    /* we need pointers to volatile variables */
378
    volatile char *buf_ptr = (volatile char *)
332
    volatile char *buf_ptr = (volatile char *)
379
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
333
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
380
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
334
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
381
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
335
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
382
   
336
   
383
    if (*in_rdptr_ptr != *in_wrptr_ptr) {
-
 
384
        /* XXX: send notification to userspace */
-
 
385
    }
-
 
386
   
-
 
387
    spinlock_unlock(&sgcn_irq.lock);
-
 
388
    interrupts_restore(ipl);   
-
 
389
 
-
 
390
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
337
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
391
       
338
       
392
        buf_ptr = (volatile char *)
339
        buf_ptr = (volatile char *)
393
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
340
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
394
        char c = *buf_ptr;
341
        char c = *buf_ptr;
Line 397... Line 344...
397
        if (c == '\r') {
344
        if (c == '\r') {
398
            c = '\n';
345
            c = '\n';
399
        }
346
        }
400
        chardev_push_character(&sgcn_io, c);   
347
        chardev_push_character(&sgcn_io, c);   
401
    }  
348
    }  
402
   
349
 
-
 
350
    interrupts_restore(ipl);   
403
    spinlock_unlock(&sgcn_input_lock);
351
    spinlock_unlock(&sgcn_input_lock);
404
}
352
}
405
 
353
 
406
/**
354
/**
-
 
355
 * Polling thread function.
-
 
356
 */
-
 
357
static void kkbdpoll(void *arg) {
-
 
358
    while (1) {
-
 
359
        if (!silent) {
-
 
360
            sgcn_poll();
-
 
361
        }
-
 
362
        thread_usleep(POLL_INTERVAL);
-
 
363
    }
-
 
364
}
-
 
365
 
-
 
366
/**
407
 * A public function which initializes I/O from/to Serengeti console
367
 * A public function which initializes I/O from/to Serengeti console
408
 * and sets it as a default input/output.
368
 * and sets it as a default input/output.
409
 */
369
 */
410
void sgcn_init(void)
370
void sgcn_init(void)
411
{
371
{
412
    sgcn_buffer_begin_init();
372
    sgcn_buffer_begin_init();
413
 
373
 
414
    kbd_type = KBD_SGCN;
374
    kbd_type = KBD_SGCN;
415
 
375
 
416
    devno_t devno = device_assign_devno();
-
 
417
    irq_initialize(&sgcn_irq);
-
 
418
    sgcn_irq.devno = devno;
-
 
419
    sgcn_irq.inr = FICTIONAL_INR;
-
 
420
    sgcn_irq.claim = sgcn_claim;
-
 
421
    sgcn_irq.handler = sgcn_irq_handler;
-
 
422
    irq_register(&sgcn_irq);
-
 
423
   
-
 
424
    sysinfo_set_item_val("kbd", NULL, true);
376
    sysinfo_set_item_val("kbd", NULL, true);
425
    sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
377
    sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
426
    sysinfo_set_item_val("kbd.devno", NULL, devno);
-
 
427
    sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR);
-
 
428
    sysinfo_set_item_val("fb.kind", NULL, 4);
378
    sysinfo_set_item_val("fb.kind", NULL, 4);
-
 
379
 
-
 
380
    thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
-
 
381
    if (!t)
-
 
382
        panic("Cannot create kkbdpoll.");
-
 
383
    thread_ready(t);
429
   
384
   
430
    chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
385
    chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
431
    stdin = &sgcn_io;
386
    stdin = &sgcn_io;
432
    stdout = &sgcn_io;
387
    stdout = &sgcn_io;
433
}
388
}