Rev 4346 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4346 | Rev 4348 | ||
---|---|---|---|
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.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> |
Line 99... | Line 99... | ||
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 */ |
- | |
105 | extern kbd_type_t kbd_type; |
- | |
106 | - | ||
107 | /** 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 */ |
108 | static uintptr_t sram_begin; |
105 | static uintptr_t sram_begin; |
109 | 106 | ||
110 | /** |
107 | /** |
111 | * starting address of the SGCN buffer, will be set by the |
108 | * starting address of the SGCN buffer, will be set by the |
Line 128... | Line 125... | ||
128 | */ |
125 | */ |
129 | SPINLOCK_INITIALIZE(sgcn_input_lock); |
126 | SPINLOCK_INITIALIZE(sgcn_input_lock); |
130 | 127 | ||
131 | 128 | ||
132 | /* functions referenced from definitions of I/O operations structures */ |
129 | /* functions referenced from definitions of I/O operations structures */ |
133 | static void sgcn_putchar(outdev_t *, const char, bool); |
130 | static void sgcn_putchar(outdev_t *, const wchar_t, bool); |
134 | 131 | ||
135 | /** SGCN output device operations */ |
132 | /** SGCN output device operations */ |
136 | static outdev_operations_t sgcnout_ops = { |
133 | static outdev_operations_t sgcnout_ops = { |
137 | .write = sgcn_putchar |
134 | .write = sgcn_putchar |
138 | }; |
135 | }; |
139 | 136 | ||
140 | /** SGCN input device operations */ |
- | |
141 | static indev_operations_t sgcnin_ops = { |
- | |
142 | .poll = NULL |
- | |
143 | }; |
- | |
144 | - | ||
145 | static indev_t sgcnin; /**< SGCN input device. */ |
- | |
146 | static outdev_t sgcnout; /**< SGCN output device. */ |
137 | static outdev_t sgcnout; /**< SGCN output device. */ |
147 | 138 | ||
148 | /** |
139 | /** |
149 | * Set some sysinfo values (SRAM address and SRAM size). |
140 | * Set some sysinfo values (SRAM address and SRAM size). |
150 | */ |
141 | */ |
Line 205... | Line 196... | ||
205 | if (initialized) |
196 | if (initialized) |
206 | return; |
197 | return; |
207 | 198 | ||
208 | init_sram_begin(); |
199 | init_sram_begin(); |
209 | 200 | ||
210 | ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0); |
201 | ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0); |
211 | 202 | ||
212 | /* lookup TOC entry with the correct key */ |
203 | /* lookup TOC entry with the correct key */ |
213 | uint32_t i; |
204 | uint32_t i; |
214 | for (i = 0; i < MAX_TOC_ENTRIES; i++) { |
205 | for (i = 0; i < MAX_TOC_ENTRIES; i++) { |
215 | if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0) |
206 | if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0) |
216 | break; |
207 | break; |
217 | } |
208 | } |
218 | ASSERT(i < MAX_TOC_ENTRIES); |
209 | ASSERT(i < MAX_TOC_ENTRIES); |
219 | 210 | ||
220 | sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset; |
211 | sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset; |
Line 262... | Line 253... | ||
262 | *buf_ptr = c; |
253 | *buf_ptr = c; |
263 | *out_wrptr_ptr = new_wrptr; |
254 | *out_wrptr_ptr = new_wrptr; |
264 | } |
255 | } |
265 | 256 | ||
266 | /** |
257 | /** |
267 | * 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 |
268 | * feed character is written ('\n'), the carriage return character ('\r') is |
- | |
269 | * written straight away. |
259 | * character is converted to CRLF. |
270 | */ |
260 | */ |
271 | static void sgcn_putchar(outdev_t *od, const char c, bool silent) |
261 | static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent) |
272 | { |
262 | { |
273 | if (!silent) { |
263 | if (!silent) { |
274 | spinlock_lock(&sgcn_output_lock); |
264 | spinlock_lock(&sgcn_output_lock); |
275 | 265 | ||
276 | sgcn_do_putchar(c); |
266 | if (ascii_check(ch)) { |
277 | if (c == '\n') |
267 | if (ch == '\n') |
278 | sgcn_do_putchar('\r'); |
268 | sgcn_do_putchar('\r'); |
- | 269 | sgcn_do_putchar(ch); |
|
- | 270 | } else |
|
- | 271 | sgcn_do_putchar(U_SPECIAL); |
|
279 | 272 | ||
280 | spinlock_unlock(&sgcn_output_lock); |
273 | spinlock_unlock(&sgcn_output_lock); |
281 | } |
274 | } |
282 | } |
275 | } |
283 | 276 | ||
284 | /** |
277 | /** |
285 | * Grabs the input for kernel. |
278 | * Grabs the input for kernel. |
286 | */ |
279 | */ |
287 | void sgcn_grab(void) |
280 | void sgcn_grab(void) |
288 | { |
281 | { |
289 | kbd_disabled = true; |
282 | kbd_disabled = false; |
290 | } |
283 | } |
291 | 284 | ||
292 | /** |
285 | /** |
293 | * Releases the input so that userspace can use it. |
286 | * Releases the input so that userspace can use it. |
294 | */ |
287 | */ |
Line 300... | Line 293... | ||
300 | /** |
293 | /** |
301 | * Function regularly called by the keyboard polling thread. Finds out whether |
294 | * Function regularly called by the keyboard polling thread. Finds out whether |
302 | * 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 |
303 | * and sends them to the upper layers of HelenOS. |
296 | * and sends them to the upper layers of HelenOS. |
304 | */ |
297 | */ |
305 | static void sgcn_poll() |
298 | static void sgcn_poll(sgcn_instance_t *instance) |
306 | { |
299 | { |
307 | uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
300 | uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
308 | uint32_t end = SGCN_BUFFER_HEADER->in_end; |
301 | uint32_t end = SGCN_BUFFER_HEADER->in_end; |
309 | uint32_t size = end - begin; |
302 | uint32_t size = end - begin; |
310 | 303 | ||
Line 318... | Line 311... | ||
318 | SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
311 | SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
319 | volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
312 | volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
320 | volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
313 | volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
321 | 314 | ||
322 | while (*in_rdptr_ptr != *in_wrptr_ptr) { |
315 | while (*in_rdptr_ptr != *in_wrptr_ptr) { |
323 | - | ||
324 | buf_ptr = (volatile char *) |
316 | buf_ptr = (volatile char *) |
325 | SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
317 | SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
326 | char c = *buf_ptr; |
318 | char c = *buf_ptr; |
327 | *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
319 | *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
328 | 320 | ||
329 | indev_push_character(&sgcnin, c); |
321 | indev_push_character(instance->srlnin, c); |
330 | } |
322 | } |
331 | 323 | ||
332 | spinlock_unlock(&sgcn_input_lock); |
324 | spinlock_unlock(&sgcn_input_lock); |
333 | } |
325 | } |
334 | 326 | ||
335 | /** |
327 | /** |
336 | * Polling thread function. |
328 | * Polling thread function. |
337 | */ |
329 | */ |
338 | static void kkbdpoll(void *arg) { |
330 | static void ksgcnpoll(void *instance) { |
339 | while (1) { |
331 | while (1) { |
340 | if (!silent) { |
332 | if (!silent) |
341 | sgcn_poll(); |
333 | sgcn_poll(instance); |
342 | } |
- | |
343 | thread_usleep(POLL_INTERVAL); |
334 | thread_usleep(POLL_INTERVAL); |
344 | } |
335 | } |
345 | } |
336 | } |
346 | 337 | ||
347 | /** |
338 | /** |
348 | * A public function which initializes input from the Serengeti console. |
339 | * A public function which initializes input from the Serengeti console. |
349 | */ |
340 | */ |
350 | indev_t *sgcnin_init(void) |
341 | sgcn_instance_t *sgcnin_init(void) |
351 | { |
342 | { |
352 | 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 | } |
|
353 | 361 | ||
354 | kbd_type = KBD_SGCN; |
362 | void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin) |
355 | 363 | { |
|
356 | sysinfo_set_item_val("kbd", NULL, true); |
364 | ASSERT(instance); |
357 | sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN); |
365 | ASSERT(srlnin); |
358 | 366 | ||
359 | thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
- | |
360 | if (!t) |
- | |
361 | panic("Cannot create kkbdpoll."); |
367 | instance->srlnin = srlnin; |
362 | thread_ready(t); |
368 | thread_ready(instance->thread); |
363 | - | ||
364 | indev_initialize("sgcnin", &sgcnin, &sgcnin_ops); |
- | |
365 | 369 | ||
366 | return &sgcnin; |
370 | sysinfo_set_item_val("kbd", NULL, true); |
367 | } |
371 | } |
368 | 372 | ||
369 | /** |
373 | /** |
370 | * A public function which initializes output to the Serengeti console. |
374 | * A public function which initializes output to the Serengeti console. |
371 | */ |
375 | */ |