Subversion Repositories HelenOS

Rev

Rev 3675 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3675 Rev 4377
Line 29... Line 29...
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/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 <func.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 71... Line 71...
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
/**
-
 
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 104... Line 94...
104
/*
94
/*
105
 * 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
106
 * offset from the console buffer beginning.
96
 * offset from the console buffer beginning.
107
 */
97
 */
108
#define SGCN_BUFFER(type, offset) \
98
#define SGCN_BUFFER(type, offset) \
109
                ((type *) (sgcn_buffer_begin + (offset)))
99
    ((type *) (sgcn_buffer_begin + (offset)))
110
 
100
 
111
/** Returns a pointer to the console buffer header. */
101
/** Returns a pointer to the console buffer header. */
112
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
102
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
113
 
103
 
114
/** defined in drivers/kbd.c */
-
 
115
extern kbd_type_t kbd_type;
-
 
116
 
-
 
117
/** 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 */
118
static uintptr_t sram_begin;
105
static uintptr_t sram_begin;
119
 
106
 
120
/**
107
/**
121
 * starting address of the SGCN buffer, will be set by the
108
 * starting address of the SGCN buffer, will be set by the
122
 * init_sgcn_buffer_begin function
109
 * init_sgcn_buffer_begin function
123
 */
110
 */
124
static uintptr_t sgcn_buffer_begin;
111
static uintptr_t sgcn_buffer_begin;
125
 
112
 
126
/**
-
 
127
 * SGCN IRQ structure. So far used only for notifying the userspace of the
113
/* 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;
114
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
 
115
 
134
/*
116
/*
135
 * 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
136
 * are together one atomic operation.
118
 * are together one atomic operation.
137
 */
119
 */
Line 143... Line 125...
143
 */
125
 */
144
SPINLOCK_INITIALIZE(sgcn_input_lock);
126
SPINLOCK_INITIALIZE(sgcn_input_lock);
145
 
127
 
146
 
128
 
147
/* functions referenced from definitions of I/O operations structures */
129
/* functions referenced from definitions of I/O operations structures */
148
static void sgcn_noop(chardev_t *);
-
 
149
static void sgcn_putchar(chardev_t *, const char);
130
static void sgcn_putchar(outdev_t *, const wchar_t, bool);
150
static char sgcn_key_read(chardev_t *);
-
 
151
 
131
 
152
/** character device operations */
132
/** SGCN output device operations */
153
static chardev_operations_t sgcn_ops = {
133
static outdev_operations_t sgcnout_ops = {
154
    .suspend = sgcn_noop,
-
 
155
    .resume = sgcn_noop,
-
 
156
    .read = sgcn_key_read,
-
 
157
    .write = sgcn_putchar
134
    .write = sgcn_putchar
158
};
135
};
159
 
136
 
160
/** SGCN character device */
137
static outdev_t sgcnout;    /**< SGCN output device. */
161
chardev_t sgcn_io;
-
 
162
 
138
 
163
/**
139
/**
164
 * Registers the physical area of the SRAM so that the userspace SGCN
140
 * Set some sysinfo values (SRAM address and SRAM size).
165
 * driver can map it. Moreover, it sets some sysinfo values (SRAM address
-
 
166
 * and SRAM size).
-
 
167
 */
141
 */
168
static void register_sram_parea(uintptr_t sram_begin_physical)
142
static void register_sram(uintptr_t sram_begin_physical)
169
{
143
{
170
    static parea_t sram_parea;
-
 
171
    sram_parea.pbase = sram_begin_physical;
-
 
172
    sram_parea.vbase = (uintptr_t) sram_begin;
-
 
173
    sram_parea.frames = MAPPED_AREA_SIZE / FRAME_SIZE;
-
 
174
    sram_parea.cacheable = false;
-
 
175
    ddi_parea_register(&sram_parea);
-
 
176
   
-
 
177
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
144
    sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
178
    sysinfo_set_item_val("sram.address.physical", NULL,
145
    sysinfo_set_item_val("sram.address.physical", NULL,
179
        sram_begin_physical);
146
        sram_begin_physical);
180
}
147
}
181
 
148
 
182
/**
149
/**
183
 * Initializes the starting address of SRAM.
150
 * Initializes the starting address of SRAM.
184
 *
151
 *
185
 * 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
186
 * 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"
187
 * property of the "/chosen" OBP node. The sram_begin variable will
154
 * property of the "/chosen" OBP node. The sram_begin variable will
188
 * 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
189
 * address.
156
 * address.
190
 *
-
 
191
 * It also registers the physical area of SRAM and sets some sysinfo
-
 
192
 * values (SRAM address and SRAM size).
-
 
193
 */
157
 */
194
static void init_sram_begin(void)
158
static void init_sram_begin(void)
195
{
159
{
196
    ofw_tree_node_t *chosen;
160
    ofw_tree_node_t *chosen;
197
    ofw_tree_property_t *iosram_toc;
161
    ofw_tree_property_t *iosram_toc;
198
    uintptr_t sram_begin_physical;
162
    uintptr_t sram_begin_physical;
199
 
163
 
200
    chosen = ofw_tree_lookup("/chosen");
164
    chosen = ofw_tree_lookup("/chosen");
201
    if (!chosen)
165
    if (!chosen)
202
        panic("Can't find /chosen.\n");
166
        panic("Cannot find '/chosen'.");
203
 
167
 
204
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
168
    iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
205
    if (!iosram_toc)
169
    if (!iosram_toc)
206
        panic("Can't find property \"iosram-toc\".\n");
170
        panic("Cannot find property 'iosram-toc'.");
207
    if (!iosram_toc->value)
171
    if (!iosram_toc->value)
208
        panic("Can't find SRAM TOC.\n");
172
        panic("Cannot find SRAM TOC.");
209
 
173
 
210
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
174
    sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
211
        + *((uint32_t *) iosram_toc->value);
175
        + *((uint32_t *) iosram_toc->value);
212
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
176
    sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
213
   
177
   
214
    register_sram_parea(sram_begin_physical);
178
    register_sram(sram_begin_physical);
215
}
179
}
216
 
180
 
217
/**
181
/**
218
 * Initializes the starting address of the SGCN buffer.
182
 * Initializes the starting address of the SGCN buffer.
219
 *
183
 *
Line 225... Line 189...
225
 * 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
226
 * under the sram.buffer.offset sysinfo key.
190
 * under the sram.buffer.offset sysinfo key.
227
 */
191
 */
228
static void sgcn_buffer_begin_init(void)
192
static void sgcn_buffer_begin_init(void)
229
{
193
{
-
 
194
    static bool initialized;
-
 
195
   
-
 
196
    if (initialized)
-
 
197
        return;
-
 
198
 
230
    init_sram_begin();
199
    init_sram_begin();
231
       
200
       
232
    ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
201
    ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
233
   
202
   
234
    /* lookup TOC entry with the correct key */
203
    /* lookup TOC entry with the correct key */
235
    uint32_t i;
204
    uint32_t i;
236
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
205
    for (i = 0; i < MAX_TOC_ENTRIES; i++) {
237
        if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
206
        if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
238
            break;
207
            break;
239
    }
208
    }
240
    ASSERT(i < MAX_TOC_ENTRIES);
209
    ASSERT(i < MAX_TOC_ENTRIES);
241
   
210
   
242
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
211
    sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
243
   
212
   
244
    sysinfo_set_item_val("sram.buffer.offset", NULL,
213
    sysinfo_set_item_val("sram.buffer.offset", NULL,
245
        SRAM_TOC->keys[i].offset);
214
        SRAM_TOC->keys[i].offset);
246
}
215
   
247
 
-
 
248
/**
-
 
249
 * Default suspend/resume operation for the input device.
-
 
250
 */
-
 
251
static void sgcn_noop(chardev_t *d)
216
    initialized = true;
252
{
-
 
253
}
217
}
254
 
218
 
255
/**
219
/**
256
 * Writes a single character to the SGCN (circular) output buffer
220
 * Writes a single character to the SGCN (circular) output buffer
257
 * 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
Line 263... Line 227...
263
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
227
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
264
    uint32_t size = end - begin;
228
    uint32_t size = end - begin;
265
   
229
   
266
    /* we need pointers to volatile variables */
230
    /* we need pointers to volatile variables */
267
    volatile char *buf_ptr = (volatile char *)
231
    volatile char *buf_ptr = (volatile char *)
268
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
232
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
269
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
233
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
270
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
234
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
271
 
235
 
272
    /*
236
    /*
273
     * Write the character and increment the write pointer modulo the
237
     * Write the character and increment the write pointer modulo the
Line 289... Line 253...
289
    *buf_ptr = c;
253
    *buf_ptr = c;
290
    *out_wrptr_ptr = new_wrptr;
254
    *out_wrptr_ptr = new_wrptr;
291
}
255
}
292
 
256
 
293
/**
257
/**
294
 * SGCN output operation. Prints a single character to the SGCN. If the line
258
 * SGCN output operation. Prints a single character to the SGCN. Newline
295
 * feed character is written ('\n'), the carriage return character ('\r') is
-
 
296
 * written straight away.
259
 * character is converted to CRLF.
297
 */
260
 */
298
static void sgcn_putchar(struct chardev * cd, const char c)
261
static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
299
{
262
{
-
 
263
    if (!silent) {
300
    spinlock_lock(&sgcn_output_lock);
264
        spinlock_lock(&sgcn_output_lock);
301
   
265
       
302
    sgcn_do_putchar(c);
266
        if (ascii_check(ch)) {
303
    if (c == '\n') {
267
            if (ch == '\n')
304
        sgcn_do_putchar('\r');
268
                sgcn_do_putchar('\r');
-
 
269
            sgcn_do_putchar(ch);
-
 
270
        } else
-
 
271
            sgcn_do_putchar(U_SPECIAL);
-
 
272
       
-
 
273
        spinlock_unlock(&sgcn_output_lock);
305
    }
274
    }
306
   
-
 
307
    spinlock_unlock(&sgcn_output_lock);
-
 
308
}
-
 
309
 
-
 
310
/**
-
 
311
 * Called when actively reading the character. Not implemented yet.
-
 
312
 */
-
 
313
static char sgcn_key_read(chardev_t *d)
-
 
314
{
-
 
315
    return (char) 0;
-
 
316
}
-
 
317
 
-
 
318
/**
-
 
319
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
320
 */
-
 
321
static irq_ownership_t sgcn_claim(void)
-
 
322
{
-
 
323
    return IRQ_DECLINE;
-
 
324
}
-
 
325
 
-
 
326
/**
-
 
327
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
328
 */
-
 
329
static void sgcn_irq_handler(irq_t *irq, void *arg, ...)
-
 
330
{
-
 
331
    panic("Not yet implemented, SGCN works in polled mode.\n");
-
 
332
}
275
}
333
 
276
 
334
/**
277
/**
335
 * Grabs the input for kernel.
278
 * Grabs the input for kernel.
336
 */
279
 */
337
void sgcn_grab(void)
280
void sgcn_grab(void)
338
{
281
{
339
    ipl_t ipl = interrupts_disable();
-
 
340
   
-
 
341
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-
 
342
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-
 
343
   
-
 
344
    /* skip all the user typed before the grab and hasn't been processed */
-
 
345
    spinlock_lock(&sgcn_input_lock);
-
 
346
    *in_rdptr_ptr = *in_wrptr_ptr;
-
 
347
    spinlock_unlock(&sgcn_input_lock);
-
 
348
 
-
 
349
    spinlock_lock(&sgcn_irq.lock);
-
 
350
    sgcn_irq.notif_cfg.notify = false;
282
    kbd_disabled = false;
351
    spinlock_unlock(&sgcn_irq.lock);
-
 
352
   
-
 
353
    interrupts_restore(ipl);
-
 
354
}
283
}
355
 
284
 
356
/**
285
/**
357
 * Releases the input so that userspace can use it.
286
 * Releases the input so that userspace can use it.
358
 */
287
 */
359
void sgcn_release(void)
288
void sgcn_release(void)
360
{
289
{
361
    ipl_t ipl = interrupts_disable();
-
 
362
    spinlock_lock(&sgcn_irq.lock);
-
 
363
    if (sgcn_irq.notif_cfg.answerbox)
-
 
364
        sgcn_irq.notif_cfg.notify = true;
290
    kbd_disabled = true;
365
    spinlock_unlock(&sgcn_irq.lock);
-
 
366
    interrupts_restore(ipl);
-
 
367
}
291
}
368
 
292
 
369
/**
293
/**
370
 * Function regularly called by the keyboard polling thread. Finds out whether
294
 * Function regularly called by the keyboard polling thread. Finds out whether
371
 * 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
372
 * and sends them to the upper layers of HelenOS.
296
 * and sends them to the upper layers of HelenOS.
373
 */
297
 */
374
void sgcn_poll(void)
298
static void sgcn_poll(sgcn_instance_t *instance)
375
{
299
{
376
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
300
    uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
377
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
301
    uint32_t end = SGCN_BUFFER_HEADER->in_end;
378
    uint32_t size = end - begin;
302
    uint32_t size = end - begin;
-
 
303
 
-
 
304
    if (kbd_disabled)
-
 
305
        return;
379
   
306
 
380
    spinlock_lock(&sgcn_input_lock);
307
    spinlock_lock(&sgcn_input_lock);
381
   
308
   
382
    ipl_t ipl = interrupts_disable();
-
 
383
    spinlock_lock(&sgcn_irq.lock);
-
 
384
   
-
 
385
    /* we need pointers to volatile variables */
309
    /* we need pointers to volatile variables */
386
    volatile char *buf_ptr = (volatile char *)
310
    volatile char *buf_ptr = (volatile char *)
387
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
311
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
388
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
312
    volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
389
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
313
    volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
390
   
314
   
391
    if (*in_rdptr_ptr != *in_wrptr_ptr) {
-
 
392
        if (sgcn_irq.notif_cfg.notify && sgcn_irq.notif_cfg.answerbox) {
-
 
393
            ipc_irq_send_notif(&sgcn_irq);
-
 
394
            spinlock_unlock(&sgcn_irq.lock);
-
 
395
            interrupts_restore(ipl);
-
 
396
            spinlock_unlock(&sgcn_input_lock);
-
 
397
            return;
-
 
398
        }
-
 
399
    }
-
 
400
   
-
 
401
    spinlock_unlock(&sgcn_irq.lock);
-
 
402
    interrupts_restore(ipl);   
-
 
403
 
-
 
404
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
315
    while (*in_rdptr_ptr != *in_wrptr_ptr) {
405
       
-
 
406
        buf_ptr = (volatile char *)
316
        buf_ptr = (volatile char *)
407
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
317
            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
408
        char c = *buf_ptr;
318
        char c = *buf_ptr;
409
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
319
        *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
410
           
320
           
411
        if (c == '\r') {
-
 
412
            c = '\n';
-
 
413
        }
-
 
414
        chardev_push_character(&sgcn_io, c);   
321
        indev_push_character(instance->srlnin, c); 
415
    }  
322
    }  
416
   
323
 
417
    spinlock_unlock(&sgcn_input_lock);
324
    spinlock_unlock(&sgcn_input_lock);
418
}
325
}
419
 
326
 
420
/**
327
/**
-
 
328
 * Polling thread function.
-
 
329
 */
-
 
330
static void ksgcnpoll(void *instance) {
-
 
331
    while (1) {
-
 
332
        if (!silent)
-
 
333
            sgcn_poll(instance);
-
 
334
        thread_usleep(POLL_INTERVAL);
-
 
335
    }
-
 
336
}
-
 
337
 
-
 
338
/**
421
 * A public function which initializes I/O from/to Serengeti console
339
 * A public function which initializes input from the Serengeti console.
422
 * and sets it as a default input/output.
-
 
423
 */
340
 */
424
void sgcn_init(void)
341
sgcn_instance_t *sgcnin_init(void)
425
{
342
{
426
    sgcn_buffer_begin_init();
343
    sgcn_buffer_begin_init();
-
 
344
   
-
 
345
    sgcn_instance_t *instance =
-
 
346
        malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
-
 
347
   
-
 
348
    if (instance) {
-
 
349
        instance->srlnin = NULL;
-
 
350
        instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
-
 
351
            "ksgcnpoll", true);
-
 
352
       
-
 
353
        if (!instance->thread) {
-
 
354
            free(instance);
-
 
355
            return NULL;
-
 
356
        }
-
 
357
    }
-
 
358
   
-
 
359
    return instance;
-
 
360
}
427
 
361
 
-
 
362
void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin)
-
 
363
{
428
    kbd_type = KBD_SGCN;
364
    ASSERT(instance);
-
 
365
    ASSERT(srlnin);
-
 
366
 
-
 
367
    instance->srlnin = srlnin;
-
 
368
    thread_ready(instance->thread);
429
 
369
 
430
    devno_t devno = device_assign_devno();
-
 
431
    irq_initialize(&sgcn_irq);
-
 
432
    sgcn_irq.devno = devno;
-
 
433
    sgcn_irq.inr = FICTIONAL_INR;
-
 
434
    sgcn_irq.claim = sgcn_claim;
-
 
435
    sgcn_irq.handler = sgcn_irq_handler;
-
 
436
    irq_register(&sgcn_irq);
-
 
437
   
-
 
438
    sysinfo_set_item_val("kbd", NULL, true);
370
    sysinfo_set_item_val("kbd", NULL, true);
-
 
371
}
-
 
372
 
-
 
373
/**
439
    sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
374
 * A public function which initializes output to the Serengeti console.
-
 
375
 */
440
    sysinfo_set_item_val("kbd.devno", NULL, devno);
376
void sgcnout_init(void)
-
 
377
{
441
    sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR);
378
    sgcn_buffer_begin_init();
-
 
379
 
442
    sysinfo_set_item_val("fb.kind", NULL, 4);
380
    sysinfo_set_item_val("fb.kind", NULL, 4);
443
   
381
 
444
    chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
382
    outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);  
445
    stdin = &sgcn_io;
-
 
446
    stdout = &sgcn_io;
383
    stdout = &sgcnout;
447
}
384
}
448
 
385
 
449
/** @}
386
/** @}
450
 */
387
 */