Subversion Repositories HelenOS

Rev

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

Rev 4070 Rev 4071
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 neccessary arangements 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
/** defined in drivers/kbd.c */
104
/** defined in drivers/kbd.c */
105
extern kbd_type_t kbd_type;
105
extern kbd_type_t kbd_type;
106
 
106
 
107
/** starting address of SRAM, will be set by the init_sram_begin function */
107
/** starting address of SRAM, will be set by the init_sram_begin function */
108
static uintptr_t sram_begin;
108
static uintptr_t sram_begin;
109
 
109
 
110
/**
110
/**
111
 * starting address of the SGCN buffer, will be set by the
111
 * starting address of the SGCN buffer, will be set by the
112
 * init_sgcn_buffer_begin function
112
 * init_sgcn_buffer_begin function
113
 */
113
 */
114
static uintptr_t sgcn_buffer_begin;
114
static uintptr_t sgcn_buffer_begin;
115
 
115
 
116
/* true iff the kernel driver should ignore pressed keys */
116
/* true iff the kernel driver should ignore pressed keys */
117
static bool kbd_disabled;
117
static bool kbd_disabled;
118
 
118
 
119
/*
119
/*
120
 * 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
121
 * are together one atomic operation.
121
 * are together one atomic operation.
122
 */
122
 */
123
SPINLOCK_INITIALIZE(sgcn_output_lock);
123
SPINLOCK_INITIALIZE(sgcn_output_lock);
124
 
124
 
125
/*
125
/*
126
 * Prevents the input buffer read/write pointers from getting to inconsistent
126
 * Prevents the input buffer read/write pointers from getting to inconsistent
127
 * state.
127
 * state.
128
 */
128
 */
129
SPINLOCK_INITIALIZE(sgcn_input_lock);
129
SPINLOCK_INITIALIZE(sgcn_input_lock);
130
 
130
 
131
 
131
 
132
/* functions referenced from definitions of I/O operations structures */
132
/* functions referenced from definitions of I/O operations structures */
133
static void sgcn_noop(chardev_t *);
133
static void sgcn_noop(chardev_t *);
134
static void sgcn_putchar(chardev_t *, const char, bool);
134
static void sgcn_putchar(chardev_t *, const char, bool);
135
static char sgcn_key_read(chardev_t *);
135
static char sgcn_key_read(chardev_t *);
136
 
136
 
137
/** character device operations */
137
/** character device operations */
138
static chardev_operations_t sgcn_ops = {
138
static chardev_operations_t sgcn_ops = {
139
    .suspend = sgcn_noop,
139
    .suspend = sgcn_noop,
140
    .resume = sgcn_noop,
140
    .resume = sgcn_noop,
141
    .read = sgcn_key_read,
141
    .read = sgcn_key_read,
142
    .write = sgcn_putchar
142
    .write = sgcn_putchar
143
};
143
};
144
 
144
 
145
/** SGCN character device */
145
/** SGCN character device */
146
chardev_t sgcn_io;
146
chardev_t sgcn_io;
147
 
147
 
-
 
148
/** Address of the chardev, which is connected to SGCN. */
-
 
149
static chardev_t *sgcnout;
-
 
150
 
148
/**
151
/**
149
 * Set some sysinfo values (SRAM address and SRAM size).
152
 * Set some sysinfo values (SRAM address and SRAM size).
150
 */
153
 */
151
static void register_sram(uintptr_t sram_begin_physical)
154
static void register_sram(uintptr_t sram_begin_physical)
152
{
155
{
153
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
156
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
154
    sysinfo_set_item_val("sram.address.physical", NULL,
157
    sysinfo_set_item_val("sram.address.physical", NULL,
155
        sram_begin_physical);
158
        sram_begin_physical);
156
}
159
}
157
 
160
 
158
/**
161
/**
159
 * Initializes the starting address of SRAM.
162
 * Initializes the starting address of SRAM.
160
 *
163
 *
161
 * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
164
 * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
162
 * physical memory, where C is the value read from the "iosram-toc"
165
 * physical memory, where C is the value read from the "iosram-toc"
163
 * property of the "/chosen" OBP node. The sram_begin variable will
166
 * property of the "/chosen" OBP node. The sram_begin variable will
164
 * be set to the virtual address which maps to the SRAM physical
167
 * be set to the virtual address which maps to the SRAM physical
165
 * address.
168
 * address.
166
 *
-
 
167
 * It also registers the physical area of SRAM and sets some sysinfo
-
 
168
 * values (SRAM address and SRAM size).
-
 
169
 */
169
 */
170
static void init_sram_begin(void)
170
static void init_sram_begin(void)
171
{
171
{
172
    ofw_tree_node_t *chosen;
172
    ofw_tree_node_t *chosen;
173
    ofw_tree_property_t *iosram_toc;
173
    ofw_tree_property_t *iosram_toc;
174
    uintptr_t sram_begin_physical;
174
    uintptr_t sram_begin_physical;
175
 
175
 
176
    chosen = ofw_tree_lookup("/chosen");
176
    chosen = ofw_tree_lookup("/chosen");
177
    if (!chosen)
177
    if (!chosen)
178
        panic("Cannot find '/chosen'.");
178
        panic("Cannot find '/chosen'.");
179
 
179
 
180
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
180
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
181
    if (!iosram_toc)
181
    if (!iosram_toc)
182
        panic("Cannot find property 'iosram-toc'.");
182
        panic("Cannot find property 'iosram-toc'.");
183
    if (!iosram_toc->value)
183
    if (!iosram_toc->value)
184
        panic("Cannot find SRAM TOC.");
184
        panic("Cannot find SRAM TOC.");
185
 
185
 
186
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
186
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
187
        + *((uint32_t *) iosram_toc->value);
187
        + *((uint32_t *) iosram_toc->value);
188
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
188
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
189
   
189
   
190
    register_sram(sram_begin_physical);
190
    register_sram(sram_begin_physical);
191
}
191
}
192
 
192
 
193
/**
193
/**
194
 * Initializes the starting address of the SGCN buffer.
194
 * Initializes the starting address of the SGCN buffer.
195
 *
195
 *
196
 * The offset of the SGCN buffer within SRAM is obtained from the
196
 * The offset of the SGCN buffer within SRAM is obtained from the
197
 * SRAM table of contents. The table of contents contains
197
 * SRAM table of contents. The table of contents contains
198
 * information about several buffers, among which there is an OBP
198
 * information about several buffers, among which there is an OBP
199
 * console buffer - this one will be used as the SGCN buffer.
199
 * console buffer - this one will be used as the SGCN buffer.
200
 *
200
 *
201
 * This function also writes the offset of the SGCN buffer within SRAM
201
 * This function also writes the offset of the SGCN buffer within SRAM
202
 * under the sram.buffer.offset sysinfo key.
202
 * under the sram.buffer.offset sysinfo key.
203
 */
203
 */
204
static void sgcn_buffer_begin_init(void)
204
static void sgcn_buffer_begin_init(void)
205
{
205
{
206
    init_sram_begin();
206
    init_sram_begin();
207
       
207
       
208
    ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
208
    ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
209
   
209
   
210
    /* lookup TOC entry with the correct key */
210
    /* lookup TOC entry with the correct key */
211
    uint32_t i;
211
    uint32_t i;
212
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
212
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
213
        if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
213
        if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
214
            break;
214
            break;
215
    }
215
    }
216
    ASSERT(i < MAX_TOC_ENTRIES);
216
    ASSERT(i < MAX_TOC_ENTRIES);
217
   
217
   
218
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
218
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
219
   
219
   
220
    sysinfo_set_item_val("sram.buffer.offset", NULL,
220
    sysinfo_set_item_val("sram.buffer.offset", NULL,
221
        SRAM_TOC->keys[i].offset);
221
        SRAM_TOC->keys[i].offset);
222
}
222
}
223
 
223
 
224
/**
224
/**
225
 * Default suspend/resume operation for the input device.
225
 * Default suspend/resume operation for the input device.
226
 */
226
 */
227
static void sgcn_noop(chardev_t *d)
227
static void sgcn_noop(chardev_t *d)
228
{
228
{
229
}
229
}
230
 
230
 
231
/**
231
/**
232
 * Writes a single character to the SGCN (circular) output buffer
232
 * Writes a single character to the SGCN (circular) output buffer
233
 * and updates the output write pointer so that SGCN gets to know
233
 * and updates the output write pointer so that SGCN gets to know
234
 * that the character has been written.
234
 * that the character has been written.
235
 */
235
 */
236
static void sgcn_do_putchar(const char c)
236
static void sgcn_do_putchar(const char c)
237
{
237
{
238
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
238
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
239
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
239
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
240
    uint32_t size = end - begin;
240
    uint32_t size = end - begin;
241
   
241
   
242
    /* we need pointers to volatile variables */
242
    /* we need pointers to volatile variables */
243
    volatile char *buf_ptr = (volatile char *)
243
    volatile char *buf_ptr = (volatile char *)
244
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
244
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
245
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
245
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
246
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
246
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
247
 
247
 
248
    /*
248
    /*
249
     * Write the character and increment the write pointer modulo the
249
     * Write the character and increment the write pointer modulo the
250
     * output buffer size. Note that if we are to rewrite a character
250
     * output buffer size. Note that if we are to rewrite a character
251
     * which has not been read by the SGCN controller yet (i.e. the output
251
     * which has not been read by the SGCN controller yet (i.e. the output
252
     * buffer is full), we need to wait until the controller reads some more
252
     * buffer is full), we need to wait until the controller reads some more
253
     * characters. We wait actively, which means that all threads waiting
253
     * characters. We wait actively, which means that all threads waiting
254
     * for the lock are blocked. However, this situation is
254
     * for the lock are blocked. However, this situation is
255
     *   1) rare - the output buffer is big, so filling the whole
255
     *   1) rare - the output buffer is big, so filling the whole
256
     *             output buffer is improbable
256
     *             output buffer is improbable
257
     *   2) short-lasting - it will take the controller only a fraction
257
     *   2) short-lasting - it will take the controller only a fraction
258
     *             of millisecond to pick the unread characters up
258
     *             of millisecond to pick the unread characters up
259
     *   3) not serious - the blocked threads are those that print something
259
     *   3) not serious - the blocked threads are those that print something
260
     *             to user console, which is not a time-critical operation
260
     *             to user console, which is not a time-critical operation
261
     */
261
     */
262
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
262
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
263
    while (*out_rdptr_ptr == new_wrptr)
263
    while (*out_rdptr_ptr == new_wrptr)
264
        ;
264
        ;
265
    *buf_ptr = c;
265
    *buf_ptr = c;
266
    *out_wrptr_ptr = new_wrptr;
266
    *out_wrptr_ptr = new_wrptr;
267
}
267
}
268
 
268
 
269
/**
269
/**
270
 * SGCN output operation. Prints a single character to the SGCN. If the line
270
 * SGCN output operation. Prints a single character to the SGCN. If the line
271
 * feed character is written ('\n'), the carriage return character ('\r') is
271
 * feed character is written ('\n'), the carriage return character ('\r') is
272
 * written straight away.
272
 * written straight away.
273
 */
273
 */
274
static void sgcn_putchar(struct chardev * cd, const char c, bool silent)
274
static void sgcn_putchar(struct chardev * cd, const char c, bool silent)
275
{
275
{
276
    if (!silent) {
276
    if (!silent) {
277
        spinlock_lock(&sgcn_output_lock);
277
        spinlock_lock(&sgcn_output_lock);
278
       
278
       
279
        sgcn_do_putchar(c);
279
        sgcn_do_putchar(c);
280
        if (c == '\n')
280
        if (c == '\n')
281
            sgcn_do_putchar('\r');
281
            sgcn_do_putchar('\r');
282
       
282
       
283
        spinlock_unlock(&sgcn_output_lock);
283
        spinlock_unlock(&sgcn_output_lock);
284
    }
284
    }
285
}
285
}
286
 
286
 
287
/**
287
/**
288
 * Called when actively reading the character. Not implemented yet.
288
 * Called when actively reading the character. Not implemented yet.
289
 */
289
 */
290
static char sgcn_key_read(chardev_t *d)
290
static char sgcn_key_read(chardev_t *d)
291
{
291
{
292
    return (char) 0;
292
    return (char) 0;
293
}
293
}
294
 
294
 
295
/**
295
/**
296
 * Grabs the input for kernel.
296
 * Grabs the input for kernel.
297
 */
297
 */
298
void sgcn_grab(void)
298
void sgcn_grab(void)
299
{
299
{
300
    kbd_disabled = true;
300
    kbd_disabled = true;
301
}
301
}
302
 
302
 
303
/**
303
/**
304
 * Releases the input so that userspace can use it.
304
 * Releases the input so that userspace can use it.
305
 */
305
 */
306
void sgcn_release(void)
306
void sgcn_release(void)
307
{
307
{
308
    kbd_disabled = true;
308
    kbd_disabled = true;
309
}
309
}
310
 
310
 
311
/**
311
/**
312
 * Function regularly called by the keyboard polling thread. Finds out whether
312
 * Function regularly called by the keyboard polling thread. Finds out whether
313
 * 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
314
 * and sends them to the upper layers of HelenOS.
314
 * and sends them to the upper layers of HelenOS.
315
 */
315
 */
316
static void sgcn_poll()
316
static void sgcn_poll()
317
{
317
{
318
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
318
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
319
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
319
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
320
    uint32_t size = end - begin;
320
    uint32_t size = end - begin;
321
 
321
 
322
    spinlock_lock(&sgcn_input_lock);
-
 
323
   
-
 
324
    ipl_t ipl = interrupts_disable();
-
 
325
 
-
 
326
    if (kbd_disabled) {
322
    if (kbd_disabled)
327
        interrupts_restore(ipl);
-
 
328
        return;
323
        return;
329
    }
324
 
-
 
325
    spinlock_lock(&sgcn_input_lock);
330
   
326
   
331
    /* we need pointers to volatile variables */
327
    /* we need pointers to volatile variables */
332
    volatile char *buf_ptr = (volatile char *)
328
    volatile char *buf_ptr = (volatile char *)
333
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
329
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
334
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
330
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
335
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
331
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
336
   
332
   
337
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
333
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
338
       
334
       
339
        buf_ptr = (volatile char *)
335
        buf_ptr = (volatile char *)
340
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
336
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
341
        char c = *buf_ptr;
337
        char c = *buf_ptr;
342
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
338
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
343
           
339
           
344
        if (c == '\r') {
340
        if (sgcnout)
345
            c = '\n';
-
 
346
        }
-
 
347
        chardev_push_character(&sgcn_io, c);   
341
            chardev_push_character(sgcnout, c);
348
    }  
342
    }  
349
 
343
 
350
    interrupts_restore(ipl);   
-
 
351
    spinlock_unlock(&sgcn_input_lock);
344
    spinlock_unlock(&sgcn_input_lock);
352
}
345
}
353
 
346
 
354
/**
347
/**
355
 * Polling thread function.
348
 * Polling thread function.
356
 */
349
 */
357
static void kkbdpoll(void *arg) {
350
static void kkbdpoll(void *arg) {
358
    while (1) {
351
    while (1) {
359
        if (!silent) {
352
        if (!silent) {
360
            sgcn_poll();
353
            sgcn_poll();
361
        }
354
        }
362
        thread_usleep(POLL_INTERVAL);
355
        thread_usleep(POLL_INTERVAL);
363
    }
356
    }
364
}
357
}
365
 
358
 
366
/**
359
/**
367
 * A public function which initializes I/O from/to Serengeti console
360
 * A public function which initializes I/O from/to Serengeti console
368
 * and sets it as a default input/output.
361
 * and sets it as a default input/output.
369
 */
362
 */
370
void sgcn_init(void)
363
void sgcn_init(chardev_t *devout)
371
{
364
{
372
    sgcn_buffer_begin_init();
365
    sgcn_buffer_begin_init();
373
 
366
 
374
    kbd_type = KBD_SGCN;
367
    kbd_type = KBD_SGCN;
375
 
368
 
376
    sysinfo_set_item_val("kbd", NULL, true);
369
    sysinfo_set_item_val("kbd", NULL, true);
377
    sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
370
    sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
378
    sysinfo_set_item_val("fb.kind", NULL, 4);
371
    sysinfo_set_item_val("fb.kind", NULL, 4);
379
 
372
 
380
    thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
373
    thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
381
    if (!t)
374
    if (!t)
382
        panic("Cannot create kkbdpoll.");
375
        panic("Cannot create kkbdpoll.");
383
    thread_ready(t);
376
    thread_ready(t);
384
   
377
   
385
    chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
378
    chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
386
    stdin = &sgcn_io;
-
 
387
    stdout = &sgcn_io;
379
    stdout = &sgcn_io;
-
 
380
 
-
 
381
    sgcnout = devout;
388
}
382
}
389
 
383
 
390
/** @}
384
/** @}
391
 */
385
 */
392
 
386