/trunk/kernel/genarch/include/kbrd/scanc_pl050.h |
---|
0,0 → 1,58 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pl050 keyboards. |
*/ |
#ifndef KERN_SCANC_PL050_H_ |
#define KERN_SCANC_PL050_H_ |
#define SC_SCAN_ESCAPE 0xE0 |
#define SC_ESC 0x76 |
#define SC_BACKSPACE 0x66 |
#define SC_LSHIFT 0x12 |
#define SC_RSHIFT 0x59 |
#define SC_CAPSLOCK 0x58 |
#define SC_SPEC_ESCAPE 0xe0 |
#define SC_LEFTARR 0x6b |
#define SC_RIGHTARR 0x74 |
#define SC_UPARR 0x75 |
#define SC_DOWNARR 0x72 |
#define SC_DELETE 0x70 |
#define SC_HOME 0x6C |
#define SC_END 0x69 |
#endif |
/** @} |
*/ |
/trunk/kernel/genarch/include/drivers/pl050/pl050.h |
---|
0,0 → 1,105 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
* @brief Describes the pl050 keyboard/mouse controller |
*/ |
/** |
* This file implements pl050 specific functions for keyboard and mouse |
*/ |
#ifndef KERN_genarch_PL050_H |
#define KERN_genarch_PL050_H |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
#include <typedefs.h> |
/* |
* pl050 register offsets from the base address |
*/ |
#define PL050_CR 0x00 |
#define PL050_STAT 0x04 |
#define PL050_DATA 0x08 |
#define PL050_CLOCKDIV 0x0C |
#define PL050_INTRSTAT 0x10 |
/* |
* Control Register Bits |
*/ |
#define PL050_CR_TYPE (1 << 5) /* Type 0: PS2/AT mode, 1: No Line control bit mode */ |
#define PL050_CR_RXINTR (1 << 4) /* Recieve Interrupt Enable */ |
#define PL050_CR_TXINTR (1 << 3) /* Transmit Interrupt Enable */ |
#define PL050_CR_INTR (1 << 2) /* Interrupt Enable */ |
#define PL050_CR_FKMID (1 << 1) /* Force KMI Data Low */ |
#define PL050_CR_FKMIC 1 /* Force KMI Clock Low */ |
/* |
* Status register bits |
*/ |
#define PL050_STAT_TXEMPTY (1 << 6) /* 1: Transmit register empty */ |
#define PL050_STAT_TXBUSY (1 << 5) /* 1: Busy, sending data */ |
#define PL050_STAT_RXFULL (1 << 4) /* 1: register Full */ |
#define PL050_STAT_RXBUSY (1 << 3) /* 1: Busy, recieving Data */ |
#define PL050_STAT_RXPARITY (1 << 2) /* odd parity of the last bit recieved */ |
#define PL050_STAT_KMIC (1 << 1) /* status of KMICLKIN */ |
#define PL050_STAT_KMID 1 /* status of KMIDATAIN */ |
/* |
* Interrupt status register bits. |
*/ |
#define PL050_TX_INTRSTAT (1 << 1) /* Transmit intr asserted */ |
#define PL050_RX_INTRSTAT 1 /* Recieve intr asserted */ |
typedef struct { |
ioport8_t *base; |
ioport8_t *data; |
ioport8_t *status; |
ioport8_t *ctrl; |
} pl050_t; |
typedef struct { |
irq_t irq; |
pl050_t *pl050; |
indev_t *kbrdin; |
} pl050_instance_t; |
extern pl050_instance_t *pl050_init(pl050_t *, inr_t); |
extern void pl050_wire(pl050_instance_t *, indev_t *); |
#endif |
/** @} |
*/ |
/trunk/kernel/genarch/Makefile.inc |
---|
110,6 → 110,12 |
genarch/src/kbrd/scanc_sun.c |
endif |
ifeq ($(CONFIG_PL050),y) |
GENARCH_SOURCES += \ |
genarch/src/kbrd/kbrd_pl050.c \ |
genarch/src/kbrd/scanc_pl050.c |
endif |
ifeq ($(CONFIG_MAC_KBD),y) |
GENARCH_SOURCES += \ |
genarch/src/kbrd/kbrd.c \ |
/trunk/kernel/genarch/src/kbrd/kbrd_pl050.c |
---|
0,0 → 1,209 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief pl050 Keyboard processing. |
*/ |
#include <genarch/kbrd/kbrd.h> |
#include <genarch/kbrd/scanc.h> |
#include <genarch/kbrd/scanc_pl050.h> |
#include <synch/spinlock.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <macros.h> |
#define PRESSED_SHIFT (1 << 0) |
#define PRESSED_CAPSLOCK (1 << 1) |
#define LOCKED_CAPSLOCK (1 << 0) |
#define PL050_KEY_RELEASE 0xF0 |
#define PL050_ESC_KEY 0xE0 |
#define PL050_CAPS_SCAN_CODE 0x58 |
#define PL050_NUM_SCAN_CODE 0x77 |
#define PL050_SCROLL_SCAN_CODE 0x7E |
static bool is_lock_key(wchar_t); |
static indev_operations_t kbrd_raw_ops = { |
.poll = NULL |
}; |
/** Process release of key. |
* |
* @param sc Scancode of the key being released. |
*/ |
static void key_released(kbrd_instance_t *instance, wchar_t sc) |
{ |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
instance->keyflags &= ~PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
instance->keyflags &= ~PRESSED_CAPSLOCK; |
if (instance->lockflags & LOCKED_CAPSLOCK) |
instance->lockflags &= ~LOCKED_CAPSLOCK; |
else |
instance->lockflags |= LOCKED_CAPSLOCK; |
break; |
default: |
break; |
} |
spinlock_unlock(&instance->keylock); |
} |
/** Process keypress. |
* |
* @param sc Scancode of the key being pressed. |
*/ |
static void key_pressed(kbrd_instance_t *instance, wchar_t sc) |
{ |
bool letter; |
bool shift; |
bool capslock; |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
instance->keyflags |= PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
instance->keyflags |= PRESSED_CAPSLOCK; |
break; |
case SC_SCAN_ESCAPE: |
break; |
default: |
letter = islower(sc_primary_map[sc]); |
shift = instance->keyflags & PRESSED_SHIFT; |
capslock = (instance->keyflags & PRESSED_CAPSLOCK) || |
(instance->lockflags & LOCKED_CAPSLOCK); |
if ((letter) && (capslock)) |
shift = !shift; |
if (shift) |
indev_push_character(instance->sink, sc_secondary_map[sc]); |
else |
indev_push_character(instance->sink, sc_primary_map[sc]); |
break; |
} |
spinlock_unlock(&instance->keylock); |
} |
static void kkbrd(void *arg) |
{ |
static int key_released_flag = 0; |
static int is_locked = 0; |
kbrd_instance_t *instance = (kbrd_instance_t *) arg; |
while (true) { |
wchar_t sc = indev_pop_character(&instance->raw); |
if (sc == PL050_KEY_RELEASE) { |
key_released_flag = 1; |
} else { |
if (key_released_flag) { |
key_released_flag = 0; |
if (is_lock_key(sc)) { |
if (!is_locked) { |
is_locked = 1; |
} else { |
is_locked = 0; |
continue; |
} |
} |
key_released(instance, sc); |
} else { |
if (is_lock_key(sc) && is_locked) |
continue; |
key_pressed(instance, sc); |
} |
} |
} |
} |
kbrd_instance_t *kbrd_init(void) |
{ |
kbrd_instance_t *instance |
= malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread |
= thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->sink = NULL; |
indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops); |
spinlock_initialize(&instance->keylock, "instance_keylock"); |
instance->keyflags = 0; |
instance->lockflags = 0; |
} |
return instance; |
} |
indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink) |
{ |
ASSERT(instance); |
ASSERT(sink); |
instance->sink = sink; |
thread_ready(instance->thread); |
return &instance->raw; |
} |
static bool is_lock_key(wchar_t sc) |
{ |
return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) || |
(sc == PL050_SCROLL_SCAN_CODE)); |
} |
/** @} |
*/ |
/trunk/kernel/genarch/src/kbrd/scanc_pl050.c |
---|
0,0 → 1,234 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, U_SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pl050 keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
#include <typedefs.h> |
#include <string.h> |
/** Primary meaning of scancodes. */ |
wchar_t sc_primary_map[] = { |
U_NULL, /* 0x00 */ |
U_SPECIAL, /* 0x01 - F9 */ |
U_SPECIAL, /* 0x02 - F7 */ |
U_SPECIAL, /* 0x03 - F5 */ |
U_SPECIAL, /* 0x04 - F3 */ |
U_SPECIAL, /* 0x05 - F1 */ |
U_SPECIAL, /* 0x06 - F2 */ |
U_SPECIAL, /* 0x07 - F12 */ |
U_SPECIAL, /* 0x08 - */ |
U_SPECIAL, /* 0x09 - F10 */ |
U_SPECIAL, /* 0x0A - F8 */ |
U_SPECIAL, /* 0x0B - F10 */ |
U_SPECIAL, /* 0x0C - F4 */ |
'\t', /* 0x0D - Tab */ |
'`', |
U_SPECIAL, /* 0x0F */ |
U_SPECIAL, /* 0x10 */ |
U_SPECIAL, /* 0x11 - LAlt */ |
U_SPECIAL, /* 0x12 - LShift */ |
U_SPECIAL, /* ox13 */ |
U_SPECIAL, /* 0x14 Ctrl */ |
'q', '1', |
U_SPECIAL, /* 0x17 */ |
U_SPECIAL, /* 0x18 */ |
U_SPECIAL, /* 0x19 */ |
'z', 's', 'a', 'w', '2', |
U_SPECIAL, /* 0x1F */ |
U_SPECIAL, /* 0x20 */ |
'c', 'x', 'd', 'e', '4', '3', |
U_SPECIAL, /* 0x27 */ |
U_SPECIAL, /* 0x28 */ |
' ', 'v', 'f', 't', 'r', '5', |
U_SPECIAL, /* 0x2F */ |
U_SPECIAL, /* 0x30 */ |
'n', 'b', 'h', 'g', 'y', '6', |
U_SPECIAL, /* 0x37 */ |
U_SPECIAL, /* 0x38 */ |
U_SPECIAL, /* 0x39 */ |
'm', 'j', 'u', '7', '8', |
U_SPECIAL, /* 0x3F */ |
U_SPECIAL, /* 0x40 */ |
',', 'k', 'i', 'o', '0', '9', |
U_SPECIAL, /* 0x47 */ |
U_SPECIAL, /* 0x48 */ |
'.', '/', 'l', ';', 'p', '-', |
U_SPECIAL, /* 0x4F */ |
U_SPECIAL, /* 0x50 */ |
U_SPECIAL, /* 0x51 */ |
'\'', |
U_SPECIAL, /* 0x53 */ |
'[', '=', |
U_SPECIAL, /* 0x56 */ |
U_SPECIAL, /* 0x57 */ |
U_SPECIAL, /* 0x58 - Caps Lock */ |
U_SPECIAL, /* 0x59 - RShift */ |
'\n', ']', |
U_SPECIAL, /* 0x5C */ |
'\\', |
U_SPECIAL, /* 0x5E */ |
U_SPECIAL, /* 0x5F */ |
U_SPECIAL, /* 0x60 */ |
U_SPECIAL, /* 0x61 */ |
U_SPECIAL, /* 0x62 */ |
U_SPECIAL, /* 0x63 */ |
U_SPECIAL, /* 0x64 */ |
U_SPECIAL, /* 0x65 */ |
'\b', /* 0x66 - backspace*/ |
U_SPECIAL, /* 0x67 */ |
U_SPECIAL, /* 0x68 */ |
U_END_ARROW, /* 0x69 */ |
U_SPECIAL, /* 0x6a */ |
U_LEFT_ARROW, /* 0x6b - Left Arrow */ |
U_SPECIAL, /* 0x6c */ |
U_SPECIAL, /* 0x6d */ |
U_SPECIAL, /* 0x6e */ |
U_SPECIAL, /* 0x6f */ |
U_SPECIAL, /* 0x70 */ |
U_DELETE, /* 0x71 - Del*/ |
U_DOWN_ARROW, /* 0x72 Down Arrow */ |
U_SPECIAL, /* 0x73 */ |
U_RIGHT_ARROW, /* 0x74 - Right Arrow */ |
U_UP_ARROW, /* 0x75 Up Arrow */ |
U_ESCAPE, /* 0x76 Esc */ |
U_SPECIAL, /* 0x77 - NumLock*/ |
U_SPECIAL, /* 0x78 F11*/ |
U_SPECIAL, /* 0x79 */ |
U_PAGE_DOWN, /* 0x7a */ |
U_SPECIAL, /* 0x7b */ |
U_SPECIAL, /* 0x7c */ |
U_PAGE_UP, /* 0x7d */ |
U_SPECIAL, /* 0x7e */ |
U_SPECIAL /* 0x7f */ |
}; |
/** Secondary meaning of scancodes. */ |
wchar_t sc_secondary_map[] = { |
U_NULL, /* 0x00 */ |
U_SPECIAL, /* 0x01 - F9 */ |
U_SPECIAL, /* 0x02 - F7 */ |
U_SPECIAL, /* 0x03 - F5 */ |
U_SPECIAL, /* 0x04 - F3 */ |
U_SPECIAL, /* 0x05 - F1 */ |
U_SPECIAL, /* 0x06 - F2 */ |
U_SPECIAL, /* 0x07 - F12 */ |
U_SPECIAL, /* 0x08 - */ |
U_SPECIAL, /* 0x09 - F10 */ |
U_SPECIAL, /* 0x0A - F8 */ |
U_SPECIAL, /* 0x0B - F10 */ |
U_SPECIAL, /* 0x0C - F4 */ |
'\t', /* 0x0D - Tab */ |
'~', |
U_SPECIAL, /* 0x0F */ |
U_SPECIAL, /* 0x10 */ |
U_SPECIAL, /* 0x11 - LAlt */ |
U_SPECIAL, /* 0x12 - LShift */ |
U_SPECIAL, /* ox13 */ |
U_SPECIAL, /* 0x14 Ctrl */ |
'Q', '!', |
U_SPECIAL, /* 0x17 */ |
U_SPECIAL, /* 0x18 */ |
U_SPECIAL, /* 0x19 */ |
'Z', 'S', 'A', 'W', '@', |
U_SPECIAL, /* 0x1F */ |
U_SPECIAL, /* 0x20 */ |
'C', 'X', 'D', 'E', '$', '#', |
U_SPECIAL, /* 0x27 */ |
U_SPECIAL, /* 0x28 */ |
' ', 'V', 'F', 'T', 'R', '%', |
U_SPECIAL, /* 0x2F */ |
U_SPECIAL, /* 0x30 */ |
'N', 'B', 'H', 'G', 'Y', '^', |
U_SPECIAL, /* 0x37 */ |
U_SPECIAL, /* 0x38 */ |
U_SPECIAL, /* 0x39 */ |
'M', 'J', 'U', '&', '*', |
U_SPECIAL, /* 0x3F */ |
U_SPECIAL, /* 0x40 */ |
'<', 'K', 'I', 'O', ')', '(', |
U_SPECIAL, /* 0x47 */ |
U_SPECIAL, /* 0x48 */ |
'>', '?', 'L', ':', 'P', '_', |
U_SPECIAL, /* 0x4F */ |
U_SPECIAL, /* 0x50 */ |
U_SPECIAL, /* 0x51 */ |
'"', |
U_SPECIAL, /* 0x53 */ |
'{', '+', |
U_SPECIAL, /* 0x56 */ |
U_SPECIAL, /* 0x57 */ |
U_SPECIAL, /* 0x58 - Caps Lock */ |
U_SPECIAL, /* 0x59 - RShift */ |
'\n', '}', |
U_SPECIAL, /* 0x5C */ |
'|', |
U_SPECIAL, /* 0x5E */ |
U_SPECIAL, /* 0x5F */ |
U_SPECIAL, /* 0x60 */ |
U_SPECIAL, /* 0x61 */ |
U_SPECIAL, /* 0x62 */ |
U_SPECIAL, /* 0x63 */ |
U_SPECIAL, /* 0x64 */ |
U_SPECIAL, /* 0x65 */ |
'\b', /* 0x66 - backspace*/ |
U_SPECIAL, /* 0x67 */ |
U_SPECIAL, /* 0x68 */ |
U_END_ARROW, /* 0x69 */ |
U_SPECIAL, /* 0x6a */ |
U_LEFT_ARROW, /* 0x6b - Left Arrow */ |
U_SPECIAL, /* 0x6c */ |
U_SPECIAL, /* 0x6d */ |
U_SPECIAL, /* 0x6e */ |
U_SPECIAL, /* 0x6f */ |
U_SPECIAL, /* 0x70 */ |
U_DELETE, /* 0x71 - Del*/ |
U_DOWN_ARROW, /* 0x72 Down Arrow */ |
U_SPECIAL, /* 0x73 */ |
U_RIGHT_ARROW, /* 0x74 - Right Arrow */ |
U_UP_ARROW, /* 0x75 Up Arrow */ |
U_ESCAPE, /* 0x76 Esc */ |
U_SPECIAL, /* 0x77 - NumLock*/ |
U_SPECIAL, /* 0x78 F11*/ |
U_SPECIAL, /* 0x79 */ |
U_PAGE_DOWN, /* 0x7a */ |
U_SPECIAL, /* 0x7b */ |
U_SPECIAL, /* 0x7c */ |
U_PAGE_UP, /* 0x7d */ |
U_SPECIAL, /* 0x7e */ |
U_SPECIAL /* 0x7f */ |
}; |
/** @} |
*/ |
/trunk/kernel/genarch/src/fb/fb.c |
---|
116,7 → 116,14 |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
} |
static void rgb_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) |
= (RED(rgb, 8) << 24) | (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8); |
} |
/** RGB 8:8:8 conversion |
* |
*/ |
470,7 → 477,7 |
pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
rgb_conv = rgb_888; |
rgb_conv = rgb_8880; |
pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
/trunk/kernel/genarch/src/drivers/pl050/pl050.c |
---|
0,0 → 1,117 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief pl050 keyboard/mouse driver. |
* |
* It takes care of low-level keyboard functions. |
*/ |
#include <genarch/drivers/pl050/pl050.h> |
#include <arch/asm.h> |
#include <console/chardev.h> |
#include <mm/slab.h> |
#include <ddi/device.h> |
#define PL050_KEY_RELEASE 0xF0 |
#define PL050_ESC_KEY 0xE0 |
#define PL050_CAPS_SCAN_CODE 0x58 |
/** Structure for pl050's IRQ. */ |
static pl050_t *pl050; |
static irq_ownership_t pl050_claim(irq_t *irq) |
{ |
uint8_t status; |
if ((status = pio_read_8(pl050->status)) & PL050_STAT_RXFULL) |
return IRQ_ACCEPT; |
else { |
return IRQ_DECLINE; |
} |
} |
static void pl050_irq_handler(irq_t *irq) |
{ |
uint8_t data; |
uint8_t status; |
pl050_instance_t *instance = irq->instance; |
while ((status = pio_read_8(pl050->status)) & PL050_STAT_RXFULL) { |
data = pio_read_8(pl050->data); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/** Initialize pl050. */ |
pl050_instance_t *pl050_init(pl050_t *dev, inr_t inr) |
{ |
pl050_instance_t *instance = |
malloc(sizeof(pl050_instance_t), FRAME_ATOMIC); |
pl050 = dev; |
if (instance) { |
instance->pl050 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = pl050_claim; |
instance->irq.handler = pl050_irq_handler; |
instance->irq.instance = instance; |
} |
return instance; |
} |
void pl050_wire(pl050_instance_t *instance, indev_t *kbrdin) |
{ |
uint8_t val; |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
val = PL050_CR_RXINTR | PL050_CR_INTR; |
pio_write_8(pl050->ctrl, val); |
/* reset the data buffer */ |
pio_read_8(pl050->data); |
} |
/** @} |
*/ |
/trunk/kernel/Makefile |
---|
343,6 → 343,9 |
clean: |
-rm -f kernel.bin kernel.raw kernel.map kernel.map.pre kernel.objdump kernel.disasm generic/src/debug/real_map.bin Makefile.depend* generic/include/arch generic/include/genarch arch/$(KARCH)/_link.ld |
find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \; |
ifeq ($(PLATFORM),arm32) |
rm -f arch/$(KARCH)/include/machine.h |
endif |
for arch in arch/* ; do \ |
[ -e $$arch/_link.ld ] && rm $$arch/_link.ld 2>/dev/null ; \ |
done ; exit 0 |
350,6 → 353,9 |
archlinks: |
ln -sfn ../../arch/$(KARCH)/include/ generic/include/arch |
ln -sfn ../../genarch/include/ generic/include/genarch |
ifeq ($(PLATFORM),arm32) |
ln -sfn mach/$(MACHINE)/$(MACHINE).h arch/$(KARCH)/include/machine.h |
endif |
depend: archlinks |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
/trunk/kernel/arch/arm32/include/exception.h |
---|
136,6 → 136,13 |
extern void install_exception_handlers(void); |
extern void exception_init(void); |
extern void print_istate(istate_t *istate); |
extern void reset_exception_entry(void); |
extern void irq_exception_entry(void); |
extern void fiq_exception_entry(void); |
extern void undef_instr_exception_entry(void); |
extern void prefetch_abort_exception_entry(void); |
extern void data_abort_exception_entry(void); |
extern void swi_exception_entry(void); |
#endif |
/trunk/kernel/arch/arm32/include/machine_func.h |
---|
0,0 → 1,132 |
/* |
* Copyright (c) 2007 Michal Kebrt |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
* @brief Declarations of machine specific functions. |
* |
* These functions enable to differentiate more kinds of ARM emulators |
* or CPUs. It's the same concept as "arch" functions on the architecture |
* level. |
*/ |
#ifndef KERN_arm32_MACHINE_FUNC_H_ |
#define KERN_arm32_MACHINE_FUNC_H_ |
#include <console/console.h> |
#include <arch/types.h> |
#include <arch/exception.h> |
#define MACHINE_GENFUNC machine_genfunc |
struct arm_machine_ops { |
void (*machine_grab_console)(void); |
void (*machine_release_console)(void); |
void (*machine_init)(void); |
void (*machine_timer_irq_start)(void); |
void (*machine_cpu_halt)(void); |
uintptr_t (*machine_get_memory_size)(void); |
void (*machine_fb_init)(void); |
void (*machine_irq_exception)(int, istate_t*); |
uintptr_t (*machine_get_fb_address)(void); |
void (*machine_frame_init)(void); |
void (*machine_output_init)(void); |
void (*machine_input_init)(void); |
}; |
extern struct arm_machine_ops machine_ops; |
/** Acquire console back for kernel. */ |
extern void machine_grab_console(void); |
/** Return console to userspace. */ |
extern void machine_release_console(void); |
/** Maps HW devices to the kernel address space using #hw_map. */ |
extern void machine_init(void); |
/** Starts timer. */ |
extern void machine_timer_irq_start(void); |
/** Halts CPU. */ |
extern void machine_cpu_halt(void); |
/** Returns size of available memory. |
* |
* @return Size of available memory. |
*/ |
extern uintptr_t machine_get_memory_size(void); |
/** Initializes the Frame Buffer |
* |
*/ |
extern void machine_fb_init(void); |
/** Interrupt exception handler. |
* |
* @param exc_no Interrupt exception number. |
* @param istate Saved processor state. |
*/ |
extern void machine_irq_exception(int exc_no, istate_t *istate); |
/** Returns address of framebuffer device. |
* |
* @return Address of framebuffer device. |
*/ |
extern uintptr_t machine_get_fb_address(void); |
/* |
* Machine specific frame initialization |
*/ |
extern void machine_frame_init(void); |
/* |
* configure the serial line output device. |
*/ |
extern void machine_output_init(void); |
/* |
* configure the serial line input device. |
*/ |
extern void machine_input_init(void); |
extern void machine_genfunc(void); |
#endif |
/** @} |
*/ |
/trunk/kernel/arch/arm32/include/mach/testarm/testarm.h |
---|
0,0 → 1,87 |
/* |
* Copyright (c) 2007 Michal Kebrt |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32gxemul GXemul |
* @brief GXemul machine specific parts. |
* @ingroup arm32 |
* @{ |
*/ |
/** @file |
* @brief GXemul peripheries drivers declarations. |
*/ |
#ifndef KERN_arm32_GXEMUL_H_ |
#define KERN_arm32_GXEMUL_H_ |
#include <arch/machine_func.h> |
/** Last interrupt number (beginning from 0) whose status is probed |
* from interrupt controller |
*/ |
#define GXEMUL_IRQC_MAX_IRQ 8 |
#define GXEMUL_KBD_IRQ 2 |
#define GXEMUL_TIMER_IRQ 4 |
/** Timer frequency */ |
#define GXEMUL_TIMER_FREQ 100 |
#define GXEMUL_KBD_ADDRESS 0x10000000 |
#define GXEMUL_MP_ADDRESS 0x11000000 |
#define GXEMUL_FB_ADDRESS 0x12000000 |
#define GXEMUL_RTC_ADDRESS 0x15000000 |
#define GXEMUL_IRQC_ADDRESS 0x16000000 |
extern void *gxemul_kbd; |
extern void *gxemul_rtc; |
extern void *gxemul_irqc; |
#define GXEMUL_HALT_OFFSET 0x010 |
#define GXEMUL_RTC_FREQ_OFFSET 0x100 |
#define GXEMUL_MP_MEMSIZE_OFFSET 0x090 |
#define GXEMUL_RTC_ACK_OFFSET 0x110 |
extern void gxemul_init(void); |
extern void gxemul_fb_init(void); |
extern void gxemul_output_init(void); |
extern void gxemul_input_init(void); |
extern void gxemul_release_console(void); |
extern void gxemul_grab_console(void); |
extern void gxemul_timer_irq_start(void); |
extern void gxemul_cpu_halt(void); |
extern void gxemul_irq_exception(int exc_no, istate_t *istate); |
extern uintptr_t gxemul_get_memory_size(void); |
extern uintptr_t gxemul_get_fb_address(void); |
extern void gxemul_fb_init(void); |
extern void gxemul_frame_init(void); |
#endif |
/** @} |
*/ |
/trunk/kernel/arch/arm32/include/mach/integratorcp/integratorcp.h |
---|
0,0 → 1,116 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32integratorcp |
* @brief Integratorcp machine specific parts. |
* @ingroup arm32 |
* @{ |
*/ |
/** @file |
* @brief Integratorcp peripheries drivers declarations. |
*/ |
#ifndef KERN_arm32_ICP_H_ |
#define KERN_arm32_ICP_H_ |
#include <arch/machine_func.h> |
/** Last interrupt number (beginning from 0) whose status is probed |
* from interrupt controller |
*/ |
#define ICP_IRQC_MAX_IRQ 8 |
#define ICP_KBD_IRQ 3 |
#define ICP_TIMER_IRQ 6 |
/** Timer frequency */ |
#define ICP_TIMER_FREQ 10000 |
#define ICP_UART 0x16000000 |
#define ICP_KBD 0x18000000 |
#define ICP_KBD_STAT 0x04 |
#define ICP_KBD_DATA 0x08 |
#define ICP_KBD_INTR_STAT 0x10 |
#define ICP_RTC 0x13000000 |
#define ICP_RTC1_LOAD_OFFSET 0x100 |
#define ICP_RTC1_READ_OFFSET 0x104 |
#define ICP_RTC1_CTL_OFFSET 0x108 |
#define ICP_RTC1_INTRCLR_OFFSET 0x10C |
#define ICP_RTC1_INTRSTAT_OFFSET 0x114 |
#define ICP_RTC1_BGLOAD_OFFSET 0x118 |
#define ICP_RTC_CTL_VALUE 0x00E2 |
#define ICP_IRQC 0x14000000 |
#define ICP_IRQC_MASK_OFFSET 0xC |
#define ICP_IRQC_UNMASK_OFFSET 0x8 |
#define ICP_FB 0x00800000 |
#define ICP_FB_FRAME (ICP_FB >> 12) |
#define ICP_FB_NUM_FRAME 512 |
#define ICP_VGA 0xC0000000 |
#define ICP_CMCR 0x10000000 |
#define ICP_SDRAM_MASK 0x1C |
#define ICP_SDRAMCR_OFFSET 0x20 |
typedef struct { |
uintptr_t uart; |
uintptr_t kbd_ctrl; |
uintptr_t kbd_stat; |
uintptr_t kbd_data; |
uintptr_t kbd_intstat; |
uintptr_t rtc; |
uintptr_t rtc1_load; |
uintptr_t rtc1_read; |
uintptr_t rtc1_ctl; |
uintptr_t rtc1_intrclr; |
uintptr_t rtc1_intrstat; |
uintptr_t rtc1_bgload; |
uintptr_t irqc; |
uintptr_t irqc_mask; |
uintptr_t irqc_unmask; |
uintptr_t vga; |
uintptr_t cmcr; |
uintptr_t sdramcr; |
} icp_hw_map_t; |
extern void icp_init(void); |
extern void icp_fb_init(void); |
extern void icp_output_init(void); |
extern void icp_input_init(void); |
extern void icp_release_console(void); |
extern void icp_grab_console(void); |
extern void icp_timer_irq_start(void); |
extern void icp_cpu_halt(void); |
extern void icp_irq_exception(int exc_no, istate_t *istate); |
extern uintptr_t icp_get_memory_size(void); |
extern uintptr_t icp_get_fb_address(void); |
extern void icp_fb_init(void); |
extern void icp_frame_init(void); |
#endif |
/** @} |
*/ |
/trunk/kernel/arch/arm32/include/drivers/gxemul.h |
---|
File deleted |
/trunk/kernel/arch/arm32/Makefile.inc |
---|
45,7 → 45,9 |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/exc_handler.S \ |
arch/$(KARCH)/src/arm32.c \ |
arch/$(KARCH)/src/machine_func.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/dummy.S \ |
arch/$(KARCH)/src/panic.S \ |
58,5 → 60,12 |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/mm/page_fault.c \ |
arch/$(KARCH)/src/drivers/gxemul.c |
arch/$(KARCH)/src/mm/page_fault.c |
ifeq ($(MACHINE), testarm) |
ARCH_SOURCES += arch/$(KARCH)/src/mach/testarm/testarm.c |
else ifeq ($(MACHINE), integratorcp) |
ARCH_SOURCES += arch/$(KARCH)/src/mach/integratorcp/integratorcp.c |
endif |
ifeq ($(CONFIG_PL050), y) |
ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c |
endif |
/trunk/kernel/arch/arm32/src/exception.c |
---|
39,7 → 39,7 |
#include <interrupt.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <arch/drivers/gxemul.h> |
#include <arch/machine.h> |
#include <print.h> |
#include <syscall/syscall.h> |
58,159 → 58,6 |
/** Size of memory block occupied by exception vectors. */ |
#define EXC_VECTORS_SIZE (EXC_VECTORS * 4) |
/** Switches to kernel stack and saves all registers there. |
* |
* Temporary exception stack is used to save a few registers |
* before stack switch takes place. |
* |
*/ |
inline static void setup_stack_and_save_regs() |
{ |
asm volatile ( |
"ldr r13, =exc_stack\n" |
"stmfd r13!, {r0}\n" |
"mrs r0, spsr\n" |
"and r0, r0, #0x1f\n" |
"cmp r0, #0x10\n" |
"bne 1f\n" |
/* prev mode was usermode */ |
"ldmfd r13!, {r0}\n" |
"ldr r13, =supervisor_sp\n" |
"ldr r13, [r13]\n" |
"stmfd r13!, {lr}\n" |
"stmfd r13!, {r0-r12}\n" |
"stmfd r13!, {r13, lr}^\n" |
"mrs r0, spsr\n" |
"stmfd r13!, {r0}\n" |
"b 2f\n" |
/* mode was not usermode */ |
"1:\n" |
"stmfd r13!, {r1, r2, r3}\n" |
"mrs r1, cpsr\n" |
"mov r2, lr\n" |
"bic r1, r1, #0x1f\n" |
"orr r1, r1, r0\n" |
"mrs r0, cpsr\n" |
"msr cpsr_c, r1\n" |
"mov r3, r13\n" |
"stmfd r13!, {r2}\n" |
"mov r2, lr\n" |
"stmfd r13!, {r4-r12}\n" |
"mov r1, r13\n" |
/* the following two lines are for debugging */ |
"mov sp, #0\n" |
"mov lr, #0\n" |
"msr cpsr_c, r0\n" |
"ldmfd r13!, {r4, r5, r6, r7}\n" |
"stmfd r1!, {r4, r5, r6}\n" |
"stmfd r1!, {r7}\n" |
"stmfd r1!, {r2}\n" |
"stmfd r1!, {r3}\n" |
"mrs r0, spsr\n" |
"stmfd r1!, {r0}\n" |
"mov r13, r1\n" |
"2:\n" |
); |
} |
/** Returns from exception mode. |
* |
* Previously saved state of registers (including control register) |
* is restored from the stack. |
*/ |
inline static void load_regs() |
{ |
asm volatile( |
"ldmfd r13!, {r0} \n" |
"msr spsr, r0 \n" |
"and r0, r0, #0x1f \n" |
"cmp r0, #0x10 \n" |
"bne 1f \n" |
/* return to user mode */ |
"ldmfd r13!, {r13, lr}^ \n" |
"b 2f \n" |
/* return to non-user mode */ |
"1:\n" |
"ldmfd r13!, {r1, r2} \n" |
"mrs r3, cpsr \n" |
"bic r3, r3, #0x1f \n" |
"orr r3, r3, r0 \n" |
"mrs r0, cpsr \n" |
"msr cpsr_c, r3 \n" |
"mov r13, r1 \n" |
"mov lr, r2 \n" |
"msr cpsr_c, r0 \n" |
/* actual return */ |
"2:\n" |
"ldmfd r13, {r0-r12, pc}^\n" |
); |
} |
/** Switch CPU to mode in which interrupts are serviced (currently it |
* is Undefined mode). |
* |
* The default mode for interrupt servicing (Interrupt Mode) |
* can not be used because of nested interrupts (which can occur |
* because interrupts are enabled in higher levels of interrupt handler). |
*/ |
inline static void switch_to_irq_servicing_mode() |
{ |
/* switch to Undefined mode */ |
asm volatile( |
/* save regs used during switching */ |
"stmfd sp!, {r0-r3} \n" |
/* save stack pointer and link register to r1, r2 */ |
"mov r1, sp \n" |
"mov r2, lr \n" |
/* mode switch */ |
"mrs r0, cpsr \n" |
"bic r0, r0, #0x1f \n" |
"orr r0, r0, #0x1b \n" |
"msr cpsr_c, r0 \n" |
/* restore saved sp and lr */ |
"mov sp, r1 \n" |
"mov lr, r2 \n" |
/* restore original regs */ |
"ldmfd sp!, {r0-r3} \n" |
); |
} |
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm volatile ( \ |
"mov r0, %[exc]\n" \ |
"mov r1, r13\n" \ |
"bl exc_dispatch\n" \ |
:: [exc] "i" (exception) \ |
);\ |
/** General exception handler. |
* |
* Stores registers, dispatches the exception, |
* and finally restores registers and returns from exception processing. |
* |
* @param exception Exception number. |
*/ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
load_regs(); |
/** Updates specified exception vector to jump to given handler. |
* |
* Addresses of handlers are stored in memory following exception vectors. |
232,71 → 79,6 |
} |
/** Low-level Reset Exception handler. */ |
static void reset_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_RESET); |
} |
/** Low-level Software Interrupt Exception handler. */ |
static void swi_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_SWI); |
} |
/** Low-level Undefined Instruction Exception handler. */ |
static void undef_instr_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_UNDEF_INSTR); |
} |
/** Low-level Fast Interrupt Exception handler. */ |
static void fiq_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_FIQ); |
} |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry(void) |
{ |
asm volatile ( |
"sub lr, lr, #4" |
); |
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
} |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry(void) |
{ |
asm volatile ( |
"sub lr, lr, #8" |
); |
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
} |
/** Low-level Interrupt Exception handler. |
* |
* CPU is switched to Undefined mode before further interrupt processing |
* because of possible occurence of nested interrupt exception, which |
* would overwrite (and thus spoil) stack pointer. |
*/ |
static void irq_exception_entry(void) |
{ |
asm volatile ( |
"sub lr, lr, #4" |
); |
setup_stack_and_save_regs(); |
switch_to_irq_servicing_mode(); |
CALL_EXC_DISPATCH(EXC_IRQ) |
load_regs(); |
} |
/** Software Interrupt handler. |
* |
* Dispatches the syscall. |
307,37 → 89,6 |
istate->r3, istate->r4, istate->r5, istate->r6); |
} |
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *((uint32_t *) gxemul_irqc); |
} |
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt and calls their handlers. |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
uint32_t sources = gxemul_irqc_get_sources(); |
unsigned int i; |
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
printf("cpu%d: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
} |
} |
} |
} |
/** Fills exception vectors with appropriate exception handlers. */ |
void install_exception_handlers(void) |
{ |
384,6 → 135,15 |
} |
#endif |
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt and calls their handlers. |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
machine_irq_exception(exc_no, istate); |
} |
/** Initializes exception handling. |
* |
* Installs low-level exception handlers and then registers |
/trunk/kernel/arch/arm32/src/start.S |
---|
36,10 → 36,32 |
kernel_image_start: |
# initialize Stack pointer for exception modes |
mrs r4, cpsr |
bic r4, r4, #0x1f |
#FIQ Mode |
orr r3, r4, #0x11 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
#IRQ Mode |
orr r3, r4, #0x12 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
#ABORT Mode |
orr r3, r4, #0x17 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
#UNDEFINED Mode |
orr r3, r4, #0x1b |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
# switch to supervisor mode |
mrs r3, cpsr |
bic r3, r3, #0x1f |
orr r3, r3, #0x13 |
orr r3, r4, #0x13 |
msr cpsr_c, r3 |
ldr sp, =temp_stack |
/trunk/kernel/arch/arm32/src/machine_func.c |
---|
0,0 → 1,147 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
* @brief Definitions of machine specific functions. |
* |
* These functions enable to differentiate more kinds of ARM emulators |
* or CPUs. It's the same concept as "arch" functions on the architecture |
* level. |
*/ |
#include <arch/machine_func.h> |
/** Acquire console back for kernel. */ |
void machine_grab_console(void) |
{ |
(machine_ops.machine_grab_console)(); |
} |
/** Return console to userspace. */ |
void machine_release_console(void) |
{ |
(machine_ops.machine_release_console)(); |
} |
/** Maps HW devices to the kernel address space using #hw_map. */ |
void machine_init(void) |
{ |
(machine_ops.machine_init)(); |
} |
/** Starts timer. */ |
void machine_timer_irq_start(void) |
{ |
(machine_ops.machine_timer_irq_start)(); |
} |
/** Halts CPU. */ |
void machine_cpu_halt(void) |
{ |
(machine_ops.machine_cpu_halt)(); |
} |
/** Returns size of available memory. |
* |
* @return Size of available memory. |
*/ |
uintptr_t machine_get_memory_size(void) |
{ |
return (machine_ops.machine_get_memory_size)(); |
} |
/** Initializes the Frame Buffer |
* |
*/ |
void machine_fb_init(void) |
{ |
(machine_ops.machine_fb_init)(); |
} |
/** Interrupt exception handler. |
* |
* @param exc_no Interrupt exception number. |
* @param istate Saved processor state. |
*/ |
void machine_irq_exception(int exc_no, istate_t *istate) |
{ |
(machine_ops.machine_irq_exception)(exc_no, istate); |
} |
/** Returns address of framebuffer device. |
* |
* @return Address of framebuffer device. |
*/ |
uintptr_t machine_get_fb_address(void) |
{ |
return (machine_ops.machine_get_fb_address)(); |
} |
/* |
* Machine specific frame initialization |
*/ |
void machine_frame_init(void) |
{ |
(machine_ops.machine_frame_init)(); |
} |
/* |
* configure the output device. |
*/ |
void machine_output_init(void) |
{ |
(machine_ops.machine_output_init)(); |
} |
/* |
* configure the input device. |
*/ |
void machine_input_init(void) |
{ |
(machine_ops.machine_input_init)(); |
} |
/* |
* Generic function to use, if sepcific function doesn't define any of the above functions. |
*/ |
void machine_genfunc() |
{ |
} |
/** @} |
*/ |
/trunk/kernel/arch/arm32/src/arm32.c |
---|
37,13 → 37,10 |
#include <config.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/drivers/dsrln/dsrlnin.h> |
#include <genarch/drivers/dsrln/dsrlnout.h> |
#include <genarch/srln/srln.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/drivers/gxemul.h> |
#include <arch/machine.h> |
#include <print.h> |
#include <config.h> |
#include <interrupt.h> |
77,7 → 74,7 |
/** Performs arm32 specific initialization afterr mm is initialized. */ |
void arch_post_mm_init(void) |
{ |
gxemul_init(); |
machine_init(); |
/* Initialize exception dispatch table */ |
exception_init(); |
84,18 → 81,10 |
interrupt_init(); |
#ifdef CONFIG_FB |
fb_properties_t prop = { |
.addr = GXEMUL_FB_ADDRESS, |
.offset = 0, |
.x = 640, |
.y = 480, |
.scan = 1920, |
.visual = VISUAL_BGR_8_8_8, |
}; |
fb_init(&prop); |
machine_fb_init(); |
#else |
#ifdef CONFIG_ARM_PRN |
dsrlnout_init((ioport8_t *) gxemul_kbd); |
machine_output_init(); |
#endif /* CONFIG_ARM_PRN */ |
#endif /* CONFIG_FB */ |
} |
126,37 → 115,13 |
*/ |
void arch_post_smp_init(void) |
{ |
#ifdef CONFIG_ARM_KBD |
/* |
* Initialize the GXemul keyboard port. Then initialize the serial line |
* module and connect it to the GXemul keyboard. |
*/ |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
machine_input_init(); |
} |
} |
/* |
* This is the necessary evil until the userspace driver is entirely |
* self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, (unative_t) gxemul_kbd); |
#endif |
} |
/** Performs arm32 specific tasks needed before the new task is run. */ |
void before_task_runs_arch(void) |
{ |
tlb_invalidate_all(); |
} |
168,6 → 133,7 |
{ |
uint8_t *stck; |
tlb_invalidate_all(); |
stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]; |
supervisor_sp = (uintptr_t) stck; |
} |
183,8 → 149,7 |
/** Halts CPU. */ |
void cpu_halt(void) |
{ |
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET)) |
= 0; |
machine_cpu_halt(); |
} |
/** Reboot. */ |
211,6 → 176,7 |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
machine_grab_console(); |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
219,6 → 185,7 |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
machine_release_console(); |
} |
/** @} |
/trunk/kernel/arch/arm32/src/mach/testarm/testarm.c |
---|
0,0 → 1,242 |
/* |
* Copyright (c) 2007 Michal Kebrt, Petr Stepan |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32gxemul |
* @{ |
*/ |
/** @file |
* @brief GXemul drivers. |
*/ |
#include <arch/exception.h> |
#include <arch/mach/testarm/testarm.h> |
#include <mm/page.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/drivers/dsrln/dsrlnin.h> |
#include <genarch/drivers/dsrln/dsrlnout.h> |
#include <genarch/srln/srln.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <config.h> |
#include <sysinfo/sysinfo.h> |
#include <interrupt.h> |
#include <print.h> |
void *gxemul_kbd; |
void *gxemul_rtc; |
void *gxemul_irqc; |
static irq_t gxemul_timer_irq; |
struct arm_machine_ops machine_ops = { |
MACHINE_GENFUNC, |
MACHINE_GENFUNC, |
gxemul_init, |
gxemul_timer_irq_start, |
gxemul_cpu_halt, |
gxemul_get_memory_size, |
gxemul_fb_init, |
gxemul_irq_exception, |
gxemul_get_fb_address, |
gxemul_frame_init, |
gxemul_output_init, |
gxemul_input_init |
}; |
void gxemul_init(void) |
{ |
gxemul_kbd = (void *) hw_map(GXEMUL_KBD_ADDRESS, PAGE_SIZE); |
gxemul_rtc = (void *) hw_map(GXEMUL_RTC_ADDRESS, PAGE_SIZE); |
gxemul_irqc = (void *) hw_map(GXEMUL_IRQC_ADDRESS, PAGE_SIZE); |
} |
void gxemul_fb_init(void) |
{ |
fb_properties_t prop = { |
.addr = GXEMUL_FB_ADDRESS, |
.offset = 0, |
.x = 640, |
.y = 480, |
.scan = 1920, |
.visual = VISUAL_BGR_8_8_8, |
}; |
fb_init(&prop); |
} |
void gxemul_output_init(void) |
{ |
dsrlnout_init((ioport8_t *) gxemul_kbd); |
} |
void gxemul_input_init(void) |
{ |
#ifdef CONFIG_ARM_KBD |
/* |
* Initialize the GXemul keyboard port. Then initialize the serial line |
* module and connect it to the GXemul keyboard. |
*/ |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
} |
} |
/* |
* This is the necessary evil until the userspace driver is entirely |
* self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, (unative_t) gxemul_kbd); |
#endif |
} |
/** Starts gxemul Real Time Clock device, which asserts regular interrupts. |
* |
* @param frequency Interrupts frequency (0 disables RTC). |
*/ |
static void gxemul_timer_start(uint32_t frequency) |
{ |
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET)) |
= frequency; |
} |
static irq_ownership_t gxemul_timer_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
/** Timer interrupt handler. |
* |
* @param irq Interrupt information. |
* @param arg Not used. |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq) |
{ |
/* |
* We are holding a lock which prevents preemption. |
* Release the lock, call clock() and reacquire the lock again. |
*/ |
spinlock_unlock(&irq->lock); |
clock(); |
spinlock_lock(&irq->lock); |
/* acknowledge tick */ |
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET)) |
= 0; |
} |
/** Initializes and registers timer interrupt handler. */ |
static void gxemul_timer_irq_init(void) |
{ |
irq_initialize(&gxemul_timer_irq); |
gxemul_timer_irq.devno = device_assign_devno(); |
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ; |
gxemul_timer_irq.claim = gxemul_timer_claim; |
gxemul_timer_irq.handler = gxemul_timer_irq_handler; |
irq_register(&gxemul_timer_irq); |
} |
/** Starts timer. |
* |
* Initiates regular timer interrupts after initializing |
* corresponding interrupt handler. |
*/ |
void gxemul_timer_irq_start(void) |
{ |
gxemul_timer_irq_init(); |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
/** Returns the size of emulated memory. |
* |
* @return Size in bytes. |
*/ |
uintptr_t gxemul_get_memory_size(void) |
{ |
return *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET)); |
} |
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *((uint32_t *) gxemul_irqc); |
} |
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt and calls their handlers. |
*/ |
void gxemul_irq_exception(int exc_no, istate_t *istate) |
{ |
uint32_t sources = gxemul_irqc_get_sources(); |
unsigned int i; |
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
printf("cpu%d: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
} |
} |
} |
} |
void gxemul_cpu_halt(void) |
{ |
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET)) = 0; |
} |
void gxemul_frame_init(void) |
{ |
} |
uintptr_t gxemul_get_fb_address() |
{ |
return ((uintptr_t)GXEMUL_FB_ADDRESS); |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/trunk/kernel/arch/arm32/src/mach/integratorcp/integratorcp.c |
---|
0,0 → 1,360 |
/* |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32integratorcp |
* @{ |
*/ |
/** @file |
* @brief ICP drivers. |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <genarch/drivers/pl050/pl050.h> |
#include <genarch/kbrd/kbrd.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <print.h> |
#include <ddi/device.h> |
#include <mm/page.h> |
#include <mm/frame.h> |
#include <arch/mm/frame.h> |
#include <arch/mach/integratorcp/integratorcp.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <ddi/ddi.h> |
#include <print.h> |
#define SDRAM_SIZE (sdram[((*(uint32_t *)(ICP_CMCR+ICP_SDRAMCR_OFFSET) & ICP_SDRAM_MASK) >> 2)]) |
static parea_t fb_parea; |
static icp_hw_map_t icp_hw_map; |
static irq_t icp_timer_irq; |
struct arm_machine_ops machine_ops = { |
MACHINE_GENFUNC, |
MACHINE_GENFUNC, |
icp_init, |
icp_timer_irq_start, |
icp_cpu_halt, |
icp_get_memory_size, |
icp_fb_init, |
icp_irq_exception, |
icp_get_fb_address, |
icp_frame_init, |
icp_output_init, |
icp_input_init |
}; |
static bool hw_map_init_called = false; |
static bool vga_init = false; |
uint32_t sdram[8] = { |
16777216, /* 16mb */ |
33554432, /* 32mb */ |
67108864, /* 64mb */ |
134217728, /* 128mb */ |
268435456, /* 256mb */ |
0, /* Reserverd */ |
0, /* Reserverd */ |
0 /* Reserverd */ |
}; |
void icp_vga_init(void); |
/** Initializes the vga |
* |
*/ |
void icp_vga_init(void) |
{ |
*(uint32_t*)((char *)(icp_hw_map.cmcr)+0x14) = 0xA05F0000; |
*(uint32_t*)((char *)(icp_hw_map.cmcr)+0x1C) = 0x12C11000; |
*(uint32_t*)icp_hw_map.vga = 0x3F1F3F9C; |
*(uint32_t*)((char *)(icp_hw_map.vga) + 0x4) = 0x080B61DF; |
*(uint32_t*)((char *)(icp_hw_map.vga) + 0x8) = 0x067F3800; |
*(uint32_t*)((char *)(icp_hw_map.vga) + 0x10) = ICP_FB; |
*(uint32_t *)((char *)(icp_hw_map.vga) + 0x1C) = 0x182B; |
*(uint32_t*)((char *)(icp_hw_map.cmcr)+0xC) = 0x33805000; |
} |
/** Returns the mask of active interrupts. */ |
static inline uint32_t icp_irqc_get_sources(void) |
{ |
return *((uint32_t *) icp_hw_map.irqc); |
} |
/** Masks interrupt. |
* |
* @param irq interrupt number |
*/ |
static inline void icp_irqc_mask(uint32_t irq) |
{ |
*((uint32_t *) icp_hw_map.irqc_mask) = (1 << irq); |
} |
/** Unmasks interrupt. |
* |
* @param irq interrupt number |
*/ |
static inline void icp_irqc_unmask(uint32_t irq) |
{ |
*((uint32_t *) icp_hw_map.irqc_unmask) |= (1 << irq); |
} |
/** Initializes the icp frame buffer */ |
void icp_fb_init(void) |
{ |
fb_properties_t prop = { |
.addr = 0, |
.offset = 0, |
.x = 640, |
.y = 480, |
.scan = 2560, |
.visual = VISUAL_RGB_8_8_8_0, |
}; |
prop.addr = icp_get_fb_address(); |
fb_init(&prop); |
fb_parea.pbase = ICP_FB; |
fb_parea.frames = 300; |
ddi_parea_register(&fb_parea); |
} |
/** Initializes icp_hw_map. */ |
void icp_init(void) |
{ |
icp_hw_map.uart = hw_map(ICP_UART, PAGE_SIZE); |
icp_hw_map.kbd_ctrl = hw_map(ICP_KBD, PAGE_SIZE); |
icp_hw_map.kbd_stat = icp_hw_map.kbd_ctrl + ICP_KBD_STAT; |
icp_hw_map.kbd_data = icp_hw_map.kbd_ctrl + ICP_KBD_DATA; |
icp_hw_map.kbd_intstat = icp_hw_map.kbd_ctrl + ICP_KBD_INTR_STAT; |
icp_hw_map.rtc = hw_map(ICP_RTC, PAGE_SIZE); |
icp_hw_map.rtc1_load = icp_hw_map.rtc + ICP_RTC1_LOAD_OFFSET; |
icp_hw_map.rtc1_read = icp_hw_map.rtc + ICP_RTC1_READ_OFFSET; |
icp_hw_map.rtc1_ctl = icp_hw_map.rtc + ICP_RTC1_CTL_OFFSET; |
icp_hw_map.rtc1_intrclr = icp_hw_map.rtc + ICP_RTC1_INTRCLR_OFFSET; |
icp_hw_map.rtc1_bgload = icp_hw_map.rtc + ICP_RTC1_BGLOAD_OFFSET; |
icp_hw_map.rtc1_intrstat = icp_hw_map.rtc + ICP_RTC1_INTRSTAT_OFFSET; |
icp_hw_map.irqc = hw_map(ICP_IRQC, PAGE_SIZE); |
icp_hw_map.irqc_mask = icp_hw_map.irqc + ICP_IRQC_MASK_OFFSET; |
icp_hw_map.irqc_unmask = icp_hw_map.irqc + ICP_IRQC_UNMASK_OFFSET; |
icp_hw_map.cmcr = hw_map(ICP_CMCR, PAGE_SIZE); |
icp_hw_map.sdramcr = icp_hw_map.cmcr + ICP_SDRAMCR_OFFSET; |
icp_hw_map.vga = hw_map(ICP_VGA, PAGE_SIZE); |
hw_map_init_called = true; |
} |
/** Acquire console back for kernel. */ |
void icp_grab_console(void) |
{ |
} |
/** Return console to userspace. */ |
void icp_release_console(void) |
{ |
} |
/** Starts icp Real Time Clock device, which asserts regular interrupts. |
* |
* @param frequency Interrupts frequency (0 disables RTC). |
*/ |
static void icp_timer_start(uint32_t frequency) |
{ |
icp_irqc_mask(ICP_TIMER_IRQ); |
*((uint32_t*) icp_hw_map.rtc1_load) = frequency; |
*((uint32_t*) icp_hw_map.rtc1_bgload) = frequency; |
*((uint32_t*) icp_hw_map.rtc1_ctl) = ICP_RTC_CTL_VALUE; |
icp_irqc_unmask(ICP_TIMER_IRQ); |
} |
static irq_ownership_t icp_timer_claim(irq_t *irq) |
{ |
if (icp_hw_map.rtc1_intrstat) { |
*((uint32_t*) icp_hw_map.rtc1_intrclr) = 1; |
return IRQ_ACCEPT; |
} else |
return IRQ_DECLINE; |
} |
/** Timer interrupt handler. |
* |
* @param irq Interrupt information. |
* @param arg Not used. |
*/ |
static void icp_timer_irq_handler(irq_t *irq) |
{ |
/* |
* We are holding a lock which prevents preemption. |
* Release the lock, call clock() and reacquire the lock again. |
*/ |
spinlock_unlock(&irq->lock); |
clock(); |
spinlock_lock(&irq->lock); |
} |
/** Initializes and registers timer interrupt handler. */ |
static void icp_timer_irq_init(void) |
{ |
irq_initialize(&icp_timer_irq); |
icp_timer_irq.devno = device_assign_devno(); |
icp_timer_irq.inr = ICP_TIMER_IRQ; |
icp_timer_irq.claim = icp_timer_claim; |
icp_timer_irq.handler = icp_timer_irq_handler; |
irq_register(&icp_timer_irq); |
} |
/** Starts timer. |
* |
* Initiates regular timer interrupts after initializing |
* corresponding interrupt handler. |
*/ |
void icp_timer_irq_start(void) |
{ |
icp_timer_irq_init(); |
icp_timer_start(ICP_TIMER_FREQ); |
} |
/** Returns the size of emulated memory. |
* |
* @return Size in bytes. |
*/ |
size_t icp_get_memory_size(void) |
{ |
if (hw_map_init_called) { |
return (sdram[((*(uint32_t *)icp_hw_map.sdramcr & ICP_SDRAM_MASK) >> 2)]); |
} else { |
return SDRAM_SIZE; |
} |
} |
/** Stops icp. */ |
void icp_cpu_halt(void) |
{ |
while (1); |
} |
/** interrupt exception handler. |
* |
* Determines sources of the interrupt from interrupt controller and |
* calls high-level handlers for them. |
* |
* @param exc_no Interrupt exception number. |
* @param istate Saved processor state. |
*/ |
void icp_irq_exception(int exc_no, istate_t *istate) |
{ |
uint32_t sources = icp_irqc_get_sources(); |
int i; |
for (i = 0; i < ICP_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
printf("cpu%d: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
} |
} |
} |
} |
/** Returns address of framebuffer device. |
* |
* @return Address of framebuffer device. |
*/ |
uintptr_t icp_get_fb_address(void) |
{ |
if (!vga_init) { |
icp_vga_init(); |
vga_init = true; |
} |
return (uintptr_t) ICP_FB; |
} |
/* |
* Integrator specific frame initialization |
*/ |
void |
icp_frame_init(void) |
{ |
frame_mark_unavailable(ICP_FB_FRAME, ICP_FB_NUM_FRAME); |
frame_mark_unavailable(0, 256); |
} |
void icp_output_init(void) |
{ |
} |
void icp_input_init(void) |
{ |
pl050_t *pl050 = malloc(sizeof(pl050_t), FRAME_ATOMIC); |
pl050->status = (ioport8_t *)icp_hw_map.kbd_stat; |
pl050->data = (ioport8_t *)icp_hw_map.kbd_data; |
pl050->ctrl = (ioport8_t *)icp_hw_map.kbd_ctrl; |
pl050_instance_t *pl050_instance = pl050_init(pl050, ICP_KBD_IRQ); |
if (pl050_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
icp_irqc_mask(ICP_KBD_IRQ); |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
pl050_wire(pl050_instance, kbrd); |
icp_irqc_unmask(ICP_KBD_IRQ); |
} |
} |
/* |
* This is the necessary evil until the userspace driver is entirely |
* self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, ICP_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.status", NULL, |
(uintptr_t) icp_hw_map.kbd_stat); |
sysinfo_set_item_val("kbd.address.data", NULL, |
(uintptr_t) icp_hw_map.kbd_data); |
} |
/** @} |
*/ |
/trunk/kernel/arch/arm32/src/mm/frame.c |
---|
35,7 → 35,7 |
#include <mm/frame.h> |
#include <arch/mm/frame.h> |
#include <arch/drivers/gxemul.h> |
#include <arch/machine.h> |
#include <config.h> |
/** Address of the last frame in the memory. */ |
44,7 → 44,7 |
/** Creates memory zones. */ |
void frame_arch_init(void) |
{ |
last_frame = *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET)); |
last_frame = machine_get_memory_size(); |
/* All memory as one zone */ |
zone_create(0, ADDR2PFN(last_frame), |
53,6 → 53,8 |
/* blacklist boot page table */ |
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME, |
BOOT_PAGE_TABLE_SIZE_IN_FRAMES); |
machine_frame_init(); |
} |
/** Frees the boot page table. */ |
/trunk/kernel/arch/arm32/src/interrupt.c |
---|
35,7 → 35,7 |
#include <arch/asm.h> |
#include <arch/regutils.h> |
#include <arch/drivers/gxemul.h> |
#include <arch/machine.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <interrupt.h> |
43,8 → 43,6 |
/** Initial size of a table holding interrupt handlers. */ |
#define IRQ_COUNT 8 |
static irq_t gxemul_timer_irq; |
/** Disable interrupts. |
* |
* @return Old interrupt priority level. |
91,41 → 89,6 |
return current_status_reg_read(); |
} |
/** Starts gxemul Real Time Clock device, which asserts regular interrupts. |
* |
* @param frequency Interrupts frequency (0 disables RTC). |
*/ |
static void gxemul_timer_start(uint32_t frequency) |
{ |
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET)) |
= frequency; |
} |
static irq_ownership_t gxemul_timer_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
/** Timer interrupt handler. |
* |
* @param irq Interrupt information. |
* @param arg Not used. |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq) |
{ |
/* |
* We are holding a lock which prevents preemption. |
* Release the lock, call clock() and reacquire the lock again. |
*/ |
spinlock_unlock(&irq->lock); |
clock(); |
spinlock_lock(&irq->lock); |
/* acknowledge tick */ |
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET)) |
= 0; |
} |
/** Initialize basic tables for exception dispatching |
* and starts the timer. |
*/ |
132,16 → 95,8 |
void interrupt_init(void) |
{ |
irq_init(IRQ_COUNT, IRQ_COUNT); |
machine_timer_irq_start(); |
irq_initialize(&gxemul_timer_irq); |
gxemul_timer_irq.devno = device_assign_devno(); |
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ; |
gxemul_timer_irq.claim = gxemul_timer_claim; |
gxemul_timer_irq.handler = gxemul_timer_irq_handler; |
irq_register(&gxemul_timer_irq); |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
/** @} |
/trunk/kernel/arch/arm32/src/exc_handler.S |
---|
0,0 → 1,199 |
# |
# Copyright (c) 2009 Vineeth Pillai |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.global irq_exception_entry |
.global fiq_exception_entry |
.global data_abort_exception_entry |
.global prefetch_abort_exception_entry |
.global undef_instr_exception_entry |
.global swi_exception_entry |
.global reset_exception_entry |
# Switches to kernel stack and saves all registers there. |
# |
# The stack frame created by the function looks like: |
# |
# |_________________| |
# | | |
# | SPSR | |
# | | |
# |_________________| |
# | Stack Pointer | |
# | of | |
# | Previous Mode | |
# |_________________| |
# | Return address | |
# | of | |
# | Previous Mode | |
# |_________________| |
# | R0 - R12 | |
# | of | |
# | Previous Mode | |
# |_________________| |
# | Return address | |
# | from | |
# |Exception Handler| |
# |_________________| |
# | | |
# |
# |
.macro SAVE_REGS_TO_STACK |
stmfd r13!, {r0-r3} |
mov r3, sp |
add sp, sp, #16 |
mrs r1, cpsr |
bic r1, r1, #0x1f |
mrs r2, spsr |
and r0, r2, #0x1f |
cmp r0, #0x10 |
bne 1f |
# prev mode was usermode |
mov r0, lr |
# Switch to supervisor mode |
orr r1, r1, #0x13 |
msr cpsr_c, r1 |
# Load sp with [supervisor_sp] |
ldr r13, =supervisor_sp |
ldr r13, [r13] |
# Populate the stack frame |
msr spsr, r2 |
mov lr, r0 |
stmfd r13!, {lr} |
stmfd r13!, {r4-r12} |
ldmfd r3!, {r4-r7} |
stmfd r13!, {r4-r7} |
stmfd r13!, {r13, lr}^ |
stmfd r13!, {r2} |
b 2f |
# mode was not usermode |
1: |
# Switch to previous mode which is undoubtedly the supervisor mode |
orr r1, r1, r0 |
mov r0, lr |
msr cpsr_c, r1 |
# Populate the stack frame |
mov r1, sp |
stmfd r13!, {r0} |
stmfd r13!, {r4-r12} |
# Store r0-r3 in r4-r7 and then push it on to stack |
ldmfd r3!, {r4-r7} |
stmfd r13!, {r4-r7} |
# Push return address and stack pointer on to stack |
stmfd r13!, {lr} |
stmfd r13!, {r1} |
mov lr, r0 |
msr spsr, r2 |
stmfd r13!, {r2} |
2: |
.endm |
.macro LOAD_REGS_FROM_STACK |
ldmfd r13!, {r0} |
msr spsr, r0 |
and r0, r0, #0x1f |
cmp r0, #0x10 |
bne 1f |
# return to user mode |
ldmfd r13!, {r13, lr}^ |
b 2f |
# return to non-user mode |
1: |
ldmfd r13!, {r1, lr} |
2: |
ldmfd r13!, {r0-r12, pc}^ |
.endm |
reset_exception_entry: |
SAVE_REGS_TO_STACK |
mov r0, #0 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
irq_exception_entry: |
sub lr, lr, #4 |
SAVE_REGS_TO_STACK |
mov r0, #5 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
fiq_exception_entry: |
sub lr, lr, #4 |
SAVE_REGS_TO_STACK |
mov r0, #6 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
undef_instr_exception_entry: |
SAVE_REGS_TO_STACK |
mov r0, #1 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
prefetch_abort_exception_entry: |
sub lr, lr, #4 |
SAVE_REGS_TO_STACK |
mov r0, #3 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
data_abort_exception_entry: |
sub lr, lr, #8 |
SAVE_REGS_TO_STACK |
mov r0, #4 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
swi_exception_entry: |
ldr r13, =exc_stack |
SAVE_REGS_TO_STACK |
mov r0, #2 |
mov r1, r13 |
bl exc_dispatch |
LOAD_REGS_FROM_STACK |
/trunk/kernel/arch/arm32/src/drivers/gxemul.c |
---|
File deleted |