Index: conf/i386.rmk =================================================================== --- conf/i386.rmk (revision 2607) +++ conf/i386.rmk (working copy) @@ -6,7 +6,7 @@ cpuid_mod_CFLAGS = $(COMMON_CFLAGS) cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += at_keyboard.mod -at_keyboard_mod_SOURCES = term/i386/pc/at_keyboard.c +at_keyboard_mod_SOURCES = term/i386/pc/at_keyboard.c kern/queue.c at_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) at_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) Index: kern/queue.c =================================================================== --- kern/queue.c (revision 0) +++ kern/queue.c (revision 0) @@ -0,0 +1,53 @@ +/* queue.c - grub queue functions */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +void +grub_queue_push (grub_queue_t queue, grub_queue_item_t item) +{ + item->next = queue->head; + item->prev = NULL; + if (queue->head) + queue->head->prev = item; + queue->head = item; + + if (! queue->tail) + /* Empty queue becomes non-empty. */ + queue->tail = item; +} + +void * +grub_queue_pop (grub_queue_t queue) +{ + grub_queue_item_t item; + + item = queue->tail; + if (queue->tail) + queue->tail = item->prev; + if (queue->tail) + queue->tail->next = NULL; + else + /* Non-empty queue becomes empty. */ + queue->head = NULL; + + return item; +} Index: include/grub/queue.h =================================================================== --- include/grub/queue.h (revision 0) +++ include/grub/queue.h (revision 0) @@ -0,0 +1,52 @@ +/* queue.h - header for grub queue */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_QUEUE_HEADER +#define GRUB_QUEUE_HEADER 1 + +#include +#include +#include /* GRUB_FIELD_MATCH */ + +struct grub_queue_item +{ + struct grub_queue_item *next, *prev; +}; +typedef struct grub_queue_item *grub_queue_item_t; + +struct grub_queue +{ + grub_queue_item_t head, tail; +}; +typedef struct grub_queue *grub_queue_t; + +void EXPORT_FUNC(grub_queue_push) (grub_queue_t queue, grub_queue_item_t item); +void * EXPORT_FUNC(grub_queue_pop) (grub_queue_t queue); + +extern void* grub_assert_fail (void); + +#define GRUB_AS_QUEUE_ITEM(ptr) \ + (GRUB_FIELD_MATCH (ptr, grub_queue_item_t, next) && GRUB_FIELD_MATCH (ptr, grub_queue_item_t, prev) ? \ + (grub_queue_item_t) ptr : grub_assert_fail ()) + +#define GRUB_AS_QUEUE_ITEM_P(pptr) \ + (GRUB_FIELD_MATCH (*pptr, grub_queue_item_t, next) && GRUB_FIELD_MATCH (*pptr, grub_queue_item_t, prev) ? \ + (grub_queue_item_t *) (void *) pptr : grub_assert_fail ()) + +#endif /* ! GRUB_QUEUE_HEADER */ Index: term/i386/pc/at_keyboard.c =================================================================== --- term/i386/pc/at_keyboard.c (revision 2607) +++ term/i386/pc/at_keyboard.c (working copy) @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,52 @@ #include #include #include +#include +#include +struct grub_at_keyboard_queue_item +{ + struct grub_at_keyboard_queue_item *next, *prev; + int key; +}; +typedef struct grub_at_keyboard_queue_item *grub_at_keyboard_queue_item_t; + +static struct grub_queue grub_at_keyboard_queue; + +static void +grub_at_keyboard_queue_push (int key) +{ + grub_at_keyboard_queue_item_t item; + item = grub_malloc (sizeof (*item)); + item->key = key; + grub_queue_push (&grub_at_keyboard_queue, GRUB_AS_QUEUE_ITEM (item)); +} + +static int +grub_at_keyboard_queue_pop (void) +{ + grub_at_keyboard_queue_item_t item; + int key; + item = grub_queue_pop (&grub_at_keyboard_queue); + if (item) + { + key = item->key; + grub_free (item); + } + else + key = -1; + return key; +} + +static int +grub_at_keyboard_queue_last (void) +{ + if (grub_at_keyboard_queue.tail) + return ((grub_at_keyboard_queue_item_t) grub_at_keyboard_queue.tail)->key; + else + return -1; +} + static short at_keyboard_status = 0; #define KEYBOARD_STATUS_SHIFT_L (1 << 0) @@ -146,7 +191,7 @@ grub_keyboard_getkey (void) /* If there is a character pending, return it; otherwise return -1. */ static int -grub_at_keyboard_checkkey (void) +grub_at_keyboard_getkey_noblock (void) { int code, key; code = grub_keyboard_getkey (); @@ -186,10 +231,24 @@ static int key += 'a' - 'A'; } } - return (int) key; + return key; } static int +grub_at_keyboard_checkkey (void) +{ + int key; + key = grub_at_keyboard_getkey_noblock (); + + /* If there was a key, queue it. */ + if (key != -1) + grub_at_keyboard_queue_push (key); + + /* Return last key from queue. */ + return grub_at_keyboard_queue_last (); +} + +static int grub_at_keyboard_getkey (void) { int key; @@ -197,6 +256,10 @@ grub_at_keyboard_getkey (void) { key = grub_at_keyboard_checkkey (); } while (key == -1); + + /* Remove it from the queue. */ + (void) grub_at_keyboard_queue_pop (); + return key; }