Subversion Repositories HelenOS

Rev

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

Rev 4311 Rev 4313
1
/*
1
/*
2
 * Copyright (c) 2008 Pavel Rimsky
2
 * Copyright (c) 2008 Pavel Rimsky
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 sparc64
29
/** @addtogroup sparc64
30
 * @{
30
 * @{
31
 */
31
 */
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.h>
38
#include <arch/drivers/sgcn.h>
38
#include <arch/drivers/sgcn.h>
39
#include <arch/drivers/kbd.h>
39
#include <arch/drivers/kbd.h>
40
#include <genarch/ofw/ofw_tree.h>
40
#include <genarch/ofw/ofw_tree.h>
41
#include <debug.h>
41
#include <debug.h>
42
#include <string.h>
42
#include <string.h>
43
#include <print.h>
43
#include <print.h>
44
#include <mm/page.h>
44
#include <mm/page.h>
45
#include <proc/thread.h>
45
#include <proc/thread.h>
46
#include <console/chardev.h>
46
#include <console/chardev.h>
47
#include <console/console.h>
47
#include <console/console.h>
48
#include <sysinfo/sysinfo.h>
48
#include <sysinfo/sysinfo.h>
49
#include <synch/spinlock.h>
49
#include <synch/spinlock.h>
50
 
50
 
51
#define POLL_INTERVAL       10000
51
#define POLL_INTERVAL       10000
52
 
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.
58
 */
58
 */
59
#define SBBC_START      0x63000000000
59
#define SBBC_START      0x63000000000
60
 
60
 
61
/* offset of SRAM within the SBBC memory */
61
/* offset of SRAM within the SBBC memory */
62
#define SBBC_SRAM_OFFSET    0x900000
62
#define SBBC_SRAM_OFFSET    0x900000
63
 
63
 
64
/* size (in bytes) of the physical memory area which will be mapped */
64
/* size (in bytes) of the physical memory area which will be mapped */
65
#define MAPPED_AREA_SIZE    (128 * 1024)
65
#define MAPPED_AREA_SIZE    (128 * 1024)
66
 
66
 
67
/* magic string contained at the beginning of SRAM */
67
/* magic string contained at the beginning of SRAM */
68
#define SRAM_TOC_MAGIC      "TOCSRAM"
68
#define SRAM_TOC_MAGIC      "TOCSRAM"
69
 
69
 
70
/*
70
/*
71
 * Key into the SRAM table of contents which identifies the entry
71
 * Key into the SRAM table of contents which identifies the entry
72
 * describing the OBP console buffer. It is worth mentioning
72
 * describing the OBP console buffer. It is worth mentioning
73
 * that the OBP console buffer is not the only console buffer
73
 * that the OBP console buffer is not the only console buffer
74
 * which can be used. It is, however, used because when the kernel
74
 * which can be used. It is, however, used because when the kernel
75
 * is running, the OBP buffer is not used by OBP any more but OBP
75
 * is running, the OBP buffer is not used by OBP any more but OBP
76
 * has already made necessary arrangements so that the output will
76
 * has already made necessary arrangements so that the output will
77
 * be read from the OBP buffer and input will go to the OBP buffer.
77
 * be read from the OBP buffer and input will go to the OBP buffer.
78
 * Therefore HelenOS needs to make no such arrangements any more.
78
 * Therefore HelenOS needs to make no such arrangements any more.
79
 */
79
 */
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
/*
85
/*
86
 * 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
87
 * offset from the SRAM beginning.
87
 * offset from the SRAM beginning.
88
 */
88
 */
89
#define SRAM(type, offset)  ((type *) (sram_begin + (offset)))
89
#define SRAM(type, offset)  ((type *) (sram_begin + (offset)))
90
 
90
 
91
/* Returns a pointer to the SRAM table of contents. */
91
/* Returns a pointer to the SRAM table of contents. */
92
#define SRAM_TOC        (SRAM(iosram_toc_t, 0))
92
#define SRAM_TOC        (SRAM(iosram_toc_t, 0))
93
 
93
 
94
/*
94
/*
95
 * Returns a pointer to the object of a given type which is placed at the given
95
 * Returns a pointer to the object of a given type which is placed at the given
96
 * offset from the console buffer beginning.
96
 * offset from the console buffer beginning.
97
 */
97
 */
98
#define SGCN_BUFFER(type, offset) \
98
#define SGCN_BUFFER(type, offset) \
99
    ((type *) (sgcn_buffer_begin + (offset)))
99
    ((type *) (sgcn_buffer_begin + (offset)))
100
 
100
 
101
/** Returns a pointer to the console buffer header. */
101
/** Returns a pointer to the console buffer header. */
102
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
102
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
103
 
103
 
104
/** starting address of SRAM, will be set by the init_sram_begin function */
104
/** starting address of SRAM, will be set by the init_sram_begin function */
105
static uintptr_t sram_begin;
105
static uintptr_t sram_begin;
106
 
106
 
107
/**
107
/**
108
 * starting address of the SGCN buffer, will be set by the
108
 * starting address of the SGCN buffer, will be set by the
109
 * init_sgcn_buffer_begin function
109
 * init_sgcn_buffer_begin function
110
 */
110
 */
111
static uintptr_t sgcn_buffer_begin;
111
static uintptr_t sgcn_buffer_begin;
112
 
112
 
113
/* true iff the kernel driver should ignore pressed keys */
113
/* true iff the kernel driver should ignore pressed keys */
114
static bool kbd_disabled;
114
static bool kbd_disabled;
115
 
115
 
116
/*
116
/*
117
 * Ensures that writing to the buffer and consequent update of the write pointer
117
 * Ensures that writing to the buffer and consequent update of the write pointer
118
 * are together one atomic operation.
118
 * are together one atomic operation.
119
 */
119
 */
120
SPINLOCK_INITIALIZE(sgcn_output_lock);
120
SPINLOCK_INITIALIZE(sgcn_output_lock);
121
 
121
 
122
/*
122
/*
123
 * Prevents the input buffer read/write pointers from getting to inconsistent
123
 * Prevents the input buffer read/write pointers from getting to inconsistent
124
 * state.
124
 * state.
125
 */
125
 */
126
SPINLOCK_INITIALIZE(sgcn_input_lock);
126
SPINLOCK_INITIALIZE(sgcn_input_lock);
127
 
127
 
128
 
128
 
129
/* functions referenced from definitions of I/O operations structures */
129
/* functions referenced from definitions of I/O operations structures */
130
static void sgcn_putchar(outdev_t *, const wchar_t, bool);
130
static void sgcn_putchar(outdev_t *, const wchar_t, bool);
131
 
131
 
132
/** SGCN output device operations */
132
/** SGCN output device operations */
133
static outdev_operations_t sgcnout_ops = {
133
static outdev_operations_t sgcnout_ops = {
134
    .write = sgcn_putchar
134
    .write = sgcn_putchar
135
};
135
};
136
 
136
 
137
/** SGCN input device operations */
-
 
138
static indev_operations_t sgcnin_ops = {
-
 
139
    .poll = NULL
-
 
140
};
-
 
141
 
-
 
142
static indev_t sgcnin;      /**< SGCN input device. */
-
 
143
static outdev_t sgcnout;    /**< SGCN output device. */
137
static outdev_t sgcnout;    /**< SGCN output device. */
144
 
138
 
145
/**
139
/**
146
 * Set some sysinfo values (SRAM address and SRAM size).
140
 * Set some sysinfo values (SRAM address and SRAM size).
147
 */
141
 */
148
static void register_sram(uintptr_t sram_begin_physical)
142
static void register_sram(uintptr_t sram_begin_physical)
149
{
143
{
150
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
144
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
151
    sysinfo_set_item_val("sram.address.physical", NULL,
145
    sysinfo_set_item_val("sram.address.physical", NULL,
152
        sram_begin_physical);
146
        sram_begin_physical);
153
}
147
}
154
 
148
 
155
/**
149
/**
156
 * Initializes the starting address of SRAM.
150
 * Initializes the starting address of SRAM.
157
 *
151
 *
158
 * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
152
 * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
159
 * physical memory, where C is the value read from the "iosram-toc"
153
 * physical memory, where C is the value read from the "iosram-toc"
160
 * property of the "/chosen" OBP node. The sram_begin variable will
154
 * property of the "/chosen" OBP node. The sram_begin variable will
161
 * be set to the virtual address which maps to the SRAM physical
155
 * be set to the virtual address which maps to the SRAM physical
162
 * address.
156
 * address.
163
 */
157
 */
164
static void init_sram_begin(void)
158
static void init_sram_begin(void)
165
{
159
{
166
    ofw_tree_node_t *chosen;
160
    ofw_tree_node_t *chosen;
167
    ofw_tree_property_t *iosram_toc;
161
    ofw_tree_property_t *iosram_toc;
168
    uintptr_t sram_begin_physical;
162
    uintptr_t sram_begin_physical;
169
 
163
 
170
    chosen = ofw_tree_lookup("/chosen");
164
    chosen = ofw_tree_lookup("/chosen");
171
    if (!chosen)
165
    if (!chosen)
172
        panic("Cannot find '/chosen'.");
166
        panic("Cannot find '/chosen'.");
173
 
167
 
174
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
168
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
175
    if (!iosram_toc)
169
    if (!iosram_toc)
176
        panic("Cannot find property 'iosram-toc'.");
170
        panic("Cannot find property 'iosram-toc'.");
177
    if (!iosram_toc->value)
171
    if (!iosram_toc->value)
178
        panic("Cannot find SRAM TOC.");
172
        panic("Cannot find SRAM TOC.");
179
 
173
 
180
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
174
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
181
        + *((uint32_t *) iosram_toc->value);
175
        + *((uint32_t *) iosram_toc->value);
182
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
176
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
183
   
177
   
184
    register_sram(sram_begin_physical);
178
    register_sram(sram_begin_physical);
185
}
179
}
186
 
180
 
187
/**
181
/**
188
 * Initializes the starting address of the SGCN buffer.
182
 * Initializes the starting address of the SGCN buffer.
189
 *
183
 *
190
 * The offset of the SGCN buffer within SRAM is obtained from the
184
 * The offset of the SGCN buffer within SRAM is obtained from the
191
 * SRAM table of contents. The table of contents contains
185
 * SRAM table of contents. The table of contents contains
192
 * information about several buffers, among which there is an OBP
186
 * information about several buffers, among which there is an OBP
193
 * console buffer - this one will be used as the SGCN buffer.
187
 * console buffer - this one will be used as the SGCN buffer.
194
 *
188
 *
195
 * This function also writes the offset of the SGCN buffer within SRAM
189
 * This function also writes the offset of the SGCN buffer within SRAM
196
 * under the sram.buffer.offset sysinfo key.
190
 * under the sram.buffer.offset sysinfo key.
197
 */
191
 */
198
static void sgcn_buffer_begin_init(void)
192
static void sgcn_buffer_begin_init(void)
199
{
193
{
200
    static bool initialized;
194
    static bool initialized;
201
   
195
   
202
    if (initialized)
196
    if (initialized)
203
        return;
197
        return;
204
 
198
 
205
    init_sram_begin();
199
    init_sram_begin();
206
       
200
       
207
    ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
201
    ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
208
   
202
   
209
    /* lookup TOC entry with the correct key */
203
    /* lookup TOC entry with the correct key */
210
    uint32_t i;
204
    uint32_t i;
211
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
205
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
212
        if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
206
        if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
213
            break;
207
            break;
214
    }
208
    }
215
    ASSERT(i < MAX_TOC_ENTRIES);
209
    ASSERT(i < MAX_TOC_ENTRIES);
216
   
210
   
217
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
211
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
218
   
212
   
219
    sysinfo_set_item_val("sram.buffer.offset", NULL,
213
    sysinfo_set_item_val("sram.buffer.offset", NULL,
220
        SRAM_TOC->keys[i].offset);
214
        SRAM_TOC->keys[i].offset);
221
   
215
   
222
    initialized = true;
216
    initialized = true;
223
}
217
}
224
 
218
 
225
/**
219
/**
226
 * Writes a single character to the SGCN (circular) output buffer
220
 * Writes a single character to the SGCN (circular) output buffer
227
 * and updates the output write pointer so that SGCN gets to know
221
 * and updates the output write pointer so that SGCN gets to know
228
 * that the character has been written.
222
 * that the character has been written.
229
 */
223
 */
230
static void sgcn_do_putchar(const char c)
224
static void sgcn_do_putchar(const char c)
231
{
225
{
232
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
226
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
233
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
227
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
234
    uint32_t size = end - begin;
228
    uint32_t size = end - begin;
235
   
229
   
236
    /* we need pointers to volatile variables */
230
    /* we need pointers to volatile variables */
237
    volatile char *buf_ptr = (volatile char *)
231
    volatile char *buf_ptr = (volatile char *)
238
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
232
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
239
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
233
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
240
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
234
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
241
 
235
 
242
    /*
236
    /*
243
     * Write the character and increment the write pointer modulo the
237
     * Write the character and increment the write pointer modulo the
244
     * output buffer size. Note that if we are to rewrite a character
238
     * output buffer size. Note that if we are to rewrite a character
245
     * which has not been read by the SGCN controller yet (i.e. the output
239
     * which has not been read by the SGCN controller yet (i.e. the output
246
     * buffer is full), we need to wait until the controller reads some more
240
     * buffer is full), we need to wait until the controller reads some more
247
     * characters. We wait actively, which means that all threads waiting
241
     * characters. We wait actively, which means that all threads waiting
248
     * for the lock are blocked. However, this situation is
242
     * for the lock are blocked. However, this situation is
249
     *   1) rare - the output buffer is big, so filling the whole
243
     *   1) rare - the output buffer is big, so filling the whole
250
     *             output buffer is improbable
244
     *             output buffer is improbable
251
     *   2) short-lasting - it will take the controller only a fraction
245
     *   2) short-lasting - it will take the controller only a fraction
252
     *             of millisecond to pick the unread characters up
246
     *             of millisecond to pick the unread characters up
253
     *   3) not serious - the blocked threads are those that print something
247
     *   3) not serious - the blocked threads are those that print something
254
     *             to user console, which is not a time-critical operation
248
     *             to user console, which is not a time-critical operation
255
     */
249
     */
256
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
250
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
257
    while (*out_rdptr_ptr == new_wrptr)
251
    while (*out_rdptr_ptr == new_wrptr)
258
        ;
252
        ;
259
    *buf_ptr = c;
253
    *buf_ptr = c;
260
    *out_wrptr_ptr = new_wrptr;
254
    *out_wrptr_ptr = new_wrptr;
261
}
255
}
262
 
256
 
263
/**
257
/**
264
 * SGCN output operation. Prints a single character to the SGCN. Newline
258
 * SGCN output operation. Prints a single character to the SGCN. Newline
265
 * character is converted to CRLF.
259
 * character is converted to CRLF.
266
 */
260
 */
267
static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
261
static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
268
{
262
{
269
    if (!silent) {
263
    if (!silent) {
270
        spinlock_lock(&sgcn_output_lock);
264
        spinlock_lock(&sgcn_output_lock);
271
       
265
       
272
        if (ascii_check(ch)) {
266
        if (ascii_check(ch)) {
273
            if (ch == '\n')
267
            if (ch == '\n')
274
                sgcn_do_putchar('\r');
268
                sgcn_do_putchar('\r');
275
            sgcn_do_putchar(ch);
269
            sgcn_do_putchar(ch);
276
        } else
270
        } else
277
            sgcn_do_putchar(U_SPECIAL);
271
            sgcn_do_putchar(U_SPECIAL);
278
       
272
       
279
        spinlock_unlock(&sgcn_output_lock);
273
        spinlock_unlock(&sgcn_output_lock);
280
    }
274
    }
281
}
275
}
282
 
276
 
283
/**
277
/**
284
 * Grabs the input for kernel.
278
 * Grabs the input for kernel.
285
 */
279
 */
286
void sgcn_grab(void)
280
void sgcn_grab(void)
287
{
281
{
288
    kbd_disabled = true;
282
    kbd_disabled = true;
289
}
283
}
290
 
284
 
291
/**
285
/**
292
 * Releases the input so that userspace can use it.
286
 * Releases the input so that userspace can use it.
293
 */
287
 */
294
void sgcn_release(void)
288
void sgcn_release(void)
295
{
289
{
296
    kbd_disabled = true;
290
    kbd_disabled = true;
297
}
291
}
298
 
292
 
299
/**
293
/**
300
 * Function regularly called by the keyboard polling thread. Finds out whether
294
 * Function regularly called by the keyboard polling thread. Finds out whether
301
 * there are some unread characters in the input queue. If so, it picks them up
295
 * there are some unread characters in the input queue. If so, it picks them up
302
 * and sends them to the upper layers of HelenOS.
296
 * and sends them to the upper layers of HelenOS.
303
 */
297
 */
304
static void sgcn_poll()
298
static void sgcn_poll(sgcn_instance_t *instance)
305
{
299
{
306
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
300
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
307
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
301
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
308
    uint32_t size = end - begin;
302
    uint32_t size = end - begin;
309
 
303
 
310
    if (kbd_disabled)
304
    if (kbd_disabled)
311
        return;
305
        return;
312
 
306
 
313
    spinlock_lock(&sgcn_input_lock);
307
    spinlock_lock(&sgcn_input_lock);
314
   
308
   
315
    /* we need pointers to volatile variables */
309
    /* we need pointers to volatile variables */
316
    volatile char *buf_ptr = (volatile char *)
310
    volatile char *buf_ptr = (volatile char *)
317
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
311
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
318
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
312
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
319
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
313
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
320
   
314
   
321
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
315
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
322
       
-
 
323
        buf_ptr = (volatile char *)
316
        buf_ptr = (volatile char *)
324
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
317
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
325
        char c = *buf_ptr;
318
        char c = *buf_ptr;
326
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
319
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
327
           
320
           
328
        indev_push_character(&sgcnin, c);  
321
        indev_push_character(instance->srlnin, c); 
329
    }  
322
    }  
330
 
323
 
331
    spinlock_unlock(&sgcn_input_lock);
324
    spinlock_unlock(&sgcn_input_lock);
332
}
325
}
333
 
326
 
334
/**
327
/**
335
 * Polling thread function.
328
 * Polling thread function.
336
 */
329
 */
337
static void kkbdpoll(void *arg) {
330
static void ksgcnpoll(void *instance) {
338
    while (1) {
331
    while (1) {
339
        if (!silent) {
332
        if (!silent)
340
            sgcn_poll();
333
            sgcn_poll(instance);
341
        }
-
 
342
        thread_usleep(POLL_INTERVAL);
334
        thread_usleep(POLL_INTERVAL);
343
    }
335
    }
344
}
336
}
345
 
337
 
346
/**
338
/**
347
 * A public function which initializes input from the Serengeti console.
339
 * A public function which initializes input from the Serengeti console.
348
 */
340
 */
349
indev_t *sgcnin_init(void)
341
sgcn_instance_t *sgcnin_init(void)
350
{
342
{
351
    sgcn_buffer_begin_init();
343
    sgcn_buffer_begin_init();
352
 
344
 
-
 
345
    sgcn_instance_t *instance =
353
    sysinfo_set_item_val("kbd", NULL, true);
346
        malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
-
 
347
    if (!instance)
-
 
348
        return NULL;
354
 
349
 
-
 
350
    instance->srlnin = NULL;
355
    thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
351
    instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
-
 
352
        "ksgcnpoll", true);
356
    if (!t)
353
    if (!instance->thread) {
357
        panic("Cannot create kkbdpoll.");
354
        free(instance);
358
    thread_ready(t);
355
        return NULL;
-
 
356
    }
359
   
357
   
-
 
358
    return instance;
-
 
359
}
-
 
360
 
360
    indev_initialize("sgcnin", &sgcnin, &sgcnin_ops);
361
void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin)
-
 
362
{
-
 
363
    ASSERT(instance);
-
 
364
    ASSERT(srlnin);
361
 
365
 
362
    return &sgcnin;
366
    instance->srlnin = srlnin;
-
 
367
    thread_ready(instance->thread);
-
 
368
 
-
 
369
    sysinfo_set_item_val("kbd", NULL, true);
363
}
370
}
364
 
371
 
365
/**
372
/**
366
 * A public function which initializes output to the Serengeti console.
373
 * A public function which initializes output to the Serengeti console.
367
 */
374
 */
368
void sgcnout_init(void)
375
void sgcnout_init(void)
369
{
376
{
370
    sgcn_buffer_begin_init();
377
    sgcn_buffer_begin_init();
371
 
378
 
372
    sysinfo_set_item_val("fb.kind", NULL, 4);
379
    sysinfo_set_item_val("fb.kind", NULL, 4);
373
 
380
 
374
    outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);  
381
    outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);  
375
    stdout = &sgcnout;
382
    stdout = &sgcnout;
376
}
383
}
377
 
384
 
378
/** @}
385
/** @}
379
 */
386
 */
380
 
387