/branches/network/kernel/genarch/include/kbrd/scanc_mac.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* 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 Macintosh ADB keyboards. |
*/ |
#ifndef KERN_SCANC_MAC_H_ |
#define KERN_SCANC_MAC_H_ |
#define SC_LSHIFT 0x38 |
#define SC_RSHIFT 0xfd /* Not used */ |
#define SC_CAPSLOCK 0xfe /* Not used */ |
#define SC_SCAN_ESCAPE 0xff /* Not used */ |
#endif |
/** @} |
*/ |
/branches/network/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 |
/** @} |
*/ |
/branches/network/kernel/genarch/include/fb/visuals.h |
---|
35,17 → 35,20 |
#ifndef KERN_VISUALS_H_ |
#define KERN_VISUALS_H_ |
#define VISUAL_INDIRECT_8 0 |
typedef enum { |
VISUAL_INDIRECT_8, |
VISUAL_RGB_5_5_5_LE, |
VISUAL_RGB_5_5_5_BE, |
VISUAL_RGB_5_6_5_LE, |
VISUAL_RGB_5_6_5_BE, |
VISUAL_BGR_8_8_8, |
VISUAL_BGR_0_8_8_8, |
VISUAL_BGR_8_8_8_0, |
VISUAL_RGB_8_8_8, |
VISUAL_RGB_0_8_8_8, |
VISUAL_RGB_8_8_8_0 |
} visual_t; |
#define VISUAL_RGB_5_5_5 1 |
#define VISUAL_RGB_5_6_5 2 |
#define VISUAL_RGB_8_8_8 3 |
#define VISUAL_RGB_8_8_8_0 4 |
#define VISUAL_RGB_0_8_8_8 5 |
#define VISUAL_BGR_0_8_8_8 6 |
#define VISUAL_BGR_8_8_8 7 |
#endif |
/** @} |
/branches/network/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 |
/** @} |
*/ |
/branches/network/kernel/genarch/include/drivers/via-cuda/cuda.h |
---|
38,14 → 38,80 |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
#include <synch/spinlock.h> |
typedef struct { |
uint8_t b; |
uint8_t pad0[0x1ff]; |
uint8_t a; |
uint8_t pad1[0x1ff]; |
uint8_t dirb; |
uint8_t pad2[0x1ff]; |
uint8_t dira; |
uint8_t pad3[0x1ff]; |
uint8_t t1cl; |
uint8_t pad4[0x1ff]; |
uint8_t t1ch; |
uint8_t pad5[0x1ff]; |
uint8_t t1ll; |
uint8_t pad6[0x1ff]; |
uint8_t t1lh; |
uint8_t pad7[0x1ff]; |
uint8_t t2cl; |
uint8_t pad8[0x1ff]; |
uint8_t t2ch; |
uint8_t pad9[0x1ff]; |
uint8_t sr; |
uint8_t pad10[0x1ff]; |
uint8_t acr; |
uint8_t pad11[0x1ff]; |
uint8_t pcr; |
uint8_t pad12[0x1ff]; |
uint8_t ifr; |
uint8_t pad13[0x1ff]; |
uint8_t ier; |
uint8_t pad14[0x1ff]; |
uint8_t anh; |
uint8_t pad15[0x1ff]; |
} cuda_t; |
enum { |
CUDA_RCV_BUF_SIZE = 5 |
}; |
enum cuda_xfer_state { |
cx_listen, |
cx_receive, |
cx_rcv_end, |
cx_send_start, |
cx_send |
}; |
typedef struct { |
irq_t irq; |
cuda_t *cuda; |
indev_t *kbrdin; |
uint8_t rcv_buf[CUDA_RCV_BUF_SIZE]; |
uint8_t snd_buf[CUDA_RCV_BUF_SIZE]; |
size_t bidx; |
size_t snd_bytes; |
enum cuda_xfer_state xstate; |
SPINLOCK_DECLARE(dev_lock); |
} cuda_instance_t; |
extern cuda_instance_t *cuda_init(cuda_t *, inr_t, cir_t, void *); |
/branches/network/kernel/genarch/Makefile.inc |
---|
110,6 → 110,18 |
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 \ |
genarch/src/kbrd/scanc_mac.c |
endif |
ifeq ($(CONFIG_SRLN),y) |
GENARCH_SOURCES += \ |
genarch/src/srln/srln.c |
/branches/network/kernel/genarch/src/kbrd/kbrd.c |
---|
45,6 → 45,10 |
#include <genarch/kbrd/scanc_sun.h> |
#endif |
#ifdef CONFIG_MAC_KBD |
#include <genarch/kbrd/scanc_mac.h> |
#endif |
#include <synch/spinlock.h> |
#include <console/chardev.h> |
#include <console/console.h> |
/branches/network/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)); |
} |
/** @} |
*/ |
/branches/network/kernel/genarch/src/kbrd/scanc_mac.c |
---|
0,0 → 1,306 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* 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 Macintosh ADB keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
#include <typedefs.h> |
#include <string.h> |
/** Primary meaning of scancodes. */ |
wchar_t sc_primary_map[SCANCODES] = { |
[0x00] = 'a', |
[0x01] = 's', |
[0x02] = 'd', |
[0x03] = 'f', |
[0x04] = 'h', |
[0x05] = 'g', |
[0x06] = 'z', |
[0x07] = 'x', |
[0x08] = 'c', |
[0x09] = 'v', |
[0x0a] = U_SPECIAL, |
[0x0b] = 'b', |
[0x0c] = 'q', |
[0x0d] = 'w', |
[0x0e] = 'e', |
[0x0f] = 'r', |
[0x10] = 'y', |
[0x11] = 't', |
[0x12] = '1', |
[0x13] = '2', |
[0x14] = '3', |
[0x15] = '4', |
[0x16] = '6', |
[0x17] = '5', |
[0x18] = '=', |
[0x19] = '9', |
[0x1a] = '7', |
[0x1b] = '-', |
[0x1c] = '8', |
[0x1d] = '0', |
[0x1e] = ']', |
[0x1f] = 'o', |
[0x20] = 'u', |
[0x21] = '[', |
[0x22] = 'i', |
[0x23] = 'p', |
[0x24] = '\n', /* Enter */ |
[0x25] = 'l', |
[0x26] = 'j', |
[0x27] = '\'', |
[0x28] = 'k', |
[0x29] = ';', |
[0x2a] = '\\', |
[0x2b] = ',', |
[0x2c] = '/', |
[0x2d] = 'n', |
[0x2e] = 'm', |
[0x2f] = '.', |
[0x30] = '\t', /* Tab */ |
[0x31] = ' ', /* Space */ |
[0x32] = '`', |
[0x33] = '\b', /* Backspace */ |
[0x34] = U_SPECIAL, |
[0x35] = U_ESCAPE, |
[0x36] = U_SPECIAL, |
[0x37] = U_SPECIAL, |
[0x38] = U_SPECIAL, |
[0x39] = U_SPECIAL, |
[0x3a] = U_SPECIAL, |
[0x3b] = U_LEFT_ARROW, |
[0x3c] = U_RIGHT_ARROW, |
[0x3d] = U_DOWN_ARROW, |
[0x3e] = U_UP_ARROW, |
[0x3f] = U_SPECIAL, |
[0x40] = U_SPECIAL, |
[0x41] = '.', /* Num Separator */ |
[0x42] = U_SPECIAL, |
[0x43] = '*', /* Num Times */ |
[0x44] = U_SPECIAL, |
[0x45] = '+', /* Num Plus */ |
[0x46] = U_SPECIAL, |
[0x47] = U_SPECIAL, |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_SPECIAL, |
[0x4b] = '/', /* Num Divide */ |
[0x4c] = U_SPECIAL, |
[0x4d] = U_SPECIAL, |
[0x4e] = '-', /* Num Minus */ |
[0x4f] = U_SPECIAL, |
[0x50] = U_SPECIAL, |
[0x51] = U_SPECIAL, |
[0x52] = '0', /* Num Zero */ |
[0x53] = '1', /* Num One */ |
[0x54] = '2', /* Num Two */ |
[0x55] = '3', /* Num Three */ |
[0x56] = '4', /* Num Four */ |
[0x57] = '5', /* Num Five */ |
[0x58] = '6', /* Num Six */ |
[0x59] = '7', /* Num Seven */ |
[0x5a] = U_SPECIAL, |
[0x5b] = '8', /* Num Eight */ |
[0x5c] = '9', /* Num Nine */ |
[0x5d] = U_SPECIAL, |
[0x5e] = U_SPECIAL, |
[0x5f] = U_SPECIAL, |
[0x60] = U_SPECIAL, |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, |
[0x63] = U_SPECIAL, |
[0x64] = U_SPECIAL, |
[0x65] = U_SPECIAL, |
[0x66] = U_SPECIAL, |
[0x67] = U_SPECIAL, |
[0x68] = U_SPECIAL, |
[0x69] = U_SPECIAL, |
[0x6a] = U_SPECIAL, |
[0x6b] = U_SPECIAL, |
[0x6c] = U_SPECIAL, |
[0x6d] = U_SPECIAL, |
[0x6e] = U_SPECIAL, |
[0x6f] = U_SPECIAL, |
[0x70] = U_SPECIAL, |
[0x71] = U_SPECIAL, |
[0x72] = U_SPECIAL, |
[0x73] = U_HOME_ARROW, |
[0x74] = U_PAGE_UP, |
[0x75] = U_DELETE, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, |
[0x78] = U_SPECIAL, |
[0x79] = U_PAGE_DOWN, |
[0x7a] = U_SPECIAL, |
[0x7b] = U_SPECIAL, |
[0x7c] = U_SPECIAL, |
[0x7d] = U_SPECIAL, |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** Secondary meaning of scancodes. */ |
wchar_t sc_secondary_map[SCANCODES] = { |
[0x00] = 'A', |
[0x01] = 'S', |
[0x02] = 'D', |
[0x03] = 'F', |
[0x04] = 'H', |
[0x05] = 'G', |
[0x06] = 'Z', |
[0x07] = 'X', |
[0x08] = 'C', |
[0x09] = 'V', |
[0x0a] = U_SPECIAL, |
[0x0b] = 'B', |
[0x0c] = 'Q', |
[0x0d] = 'W', |
[0x0e] = 'E', |
[0x0f] = 'R', |
[0x10] = 'Y', |
[0x11] = 'T', |
[0x12] = '!', |
[0x13] = '@', |
[0x14] = '#', |
[0x15] = '$', |
[0x16] = '^', |
[0x17] = '%', |
[0x18] = '+', |
[0x19] = '(', |
[0x1a] = '&', |
[0x1b] = '_', |
[0x1c] = '*', |
[0x1d] = ')', |
[0x1e] = '}', |
[0x1f] = 'O', |
[0x20] = 'U', |
[0x21] = '{', |
[0x22] = 'I', |
[0x23] = 'P', |
[0x24] = '\n', /* Enter */ |
[0x25] = 'L', |
[0x26] = 'J', |
[0x27] = '"', |
[0x28] = 'K', |
[0x29] = ':', |
[0x2a] = '|', |
[0x2b] = '<', |
[0x2c] = '?', |
[0x2d] = 'N', |
[0x2e] = 'M', |
[0x2f] = '>', |
[0x30] = '\t', /* Tab */ |
[0x31] = ' ', /* Space */ |
[0x32] = '~', |
[0x33] = '\b', /* Backspace */ |
[0x34] = U_SPECIAL, |
[0x35] = U_SPECIAL, |
[0x36] = U_SPECIAL, |
[0x37] = U_SPECIAL, |
[0x38] = U_SPECIAL, |
[0x39] = U_SPECIAL, |
[0x3a] = U_SPECIAL, |
[0x3b] = U_SPECIAL, |
[0x3c] = U_SPECIAL, |
[0x3d] = U_SPECIAL, |
[0x3e] = U_SPECIAL, |
[0x3f] = U_SPECIAL, |
[0x40] = U_SPECIAL, |
[0x41] = '.', /* Num Separator */ |
[0x42] = U_SPECIAL, |
[0x43] = '*', /* Num Times */ |
[0x44] = U_SPECIAL, |
[0x45] = '+', /* Num Plus */ |
[0x46] = U_SPECIAL, |
[0x47] = U_SPECIAL, |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_SPECIAL, |
[0x4b] = '/', /* Num Divide */ |
[0x4c] = U_SPECIAL, |
[0x4d] = U_SPECIAL, |
[0x4e] = '-', /* Num Minus */ |
[0x4f] = U_SPECIAL, |
[0x50] = U_SPECIAL, |
[0x51] = U_SPECIAL, |
[0x52] = '0', /* Num Zero */ |
[0x53] = '1', /* Num One */ |
[0x54] = '2', /* Num Two */ |
[0x55] = '3', /* Num Three */ |
[0x56] = '4', /* Num Four */ |
[0x57] = '5', /* Num Five */ |
[0x58] = '6', /* Num Six */ |
[0x59] = '7', /* Num Seven */ |
[0x5a] = U_SPECIAL, |
[0x5b] = '8', /* Num Eight */ |
[0x5c] = '9', /* Num Nine */ |
[0x5d] = U_SPECIAL, |
[0x5e] = U_SPECIAL, |
[0x5f] = U_SPECIAL, |
[0x60] = U_SPECIAL, |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, |
[0x63] = U_SPECIAL, |
[0x64] = U_SPECIAL, |
[0x65] = U_SPECIAL, |
[0x66] = U_SPECIAL, |
[0x67] = U_SPECIAL, |
[0x68] = U_SPECIAL, |
[0x69] = U_SPECIAL, |
[0x6a] = U_SPECIAL, |
[0x6b] = U_SPECIAL, |
[0x6c] = U_SPECIAL, |
[0x6d] = U_SPECIAL, |
[0x6e] = U_SPECIAL, |
[0x6f] = U_SPECIAL, |
[0x70] = U_SPECIAL, |
[0x71] = U_SPECIAL, |
[0x72] = U_SPECIAL, |
[0x73] = U_SPECIAL, |
[0x74] = U_SPECIAL, |
[0x75] = U_SPECIAL, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, |
[0x78] = U_SPECIAL, |
[0x79] = U_SPECIAL, |
[0x7a] = U_SPECIAL, |
[0x7b] = U_SPECIAL, |
[0x7c] = U_SPECIAL, |
[0x7d] = U_SPECIAL, |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** @} |
*/ |
/branches/network/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 */ |
}; |
/** @} |
*/ |
/branches/network/kernel/genarch/src/fb/fb.c |
---|
50,6 → 50,7 |
#include <string.h> |
#include <ddi/ddi.h> |
#include <arch/types.h> |
#include <byteorder.h> |
SPINLOCK_INITIALIZE(fb_lock); |
80,9 → 81,9 |
#define FG_COLOR 0xffff00 |
#define INV_COLOR 0xaaaaaa |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) |
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
97,69 → 98,79 |
static void (*rgb_conv)(void *, uint32_t); |
/** ARGB 8:8:8:8 conversion |
/* |
* RGB conversion functions. |
* |
* These functions write an RGB value to some memory in some predefined format. |
* The naming convention corresponds to the format created by these functions. |
* The functions use the so called network order (i.e. big endian) with respect |
* to their names. |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = rgb & 0xffffff; |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8))); |
} |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8))); |
} |
static void rgb_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0); |
} |
/** RGB 8:8:8 conversion |
* |
*/ |
static void bgr_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0); |
} |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
static void rgb_555_be(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
} |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
static void rgb_555_le(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
} |
static void rgb_565_be(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
} |
/** RGB 5:6:5 conversion |
* |
*/ |
static void rgb_565(void *dst, uint32_t rgb) |
static void rgb_565_le(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
} |
/** RGB 3:2:3 |
/** BGR 3:2:3 |
* |
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer |
* will most likely use a color palette. The color appearance |
176,7 → 187,7 |
* 0 and 255 to other colors. |
* |
*/ |
static void rgb_323(void *dst, uint32_t rgb) |
static void bgr_323(void *dst, uint32_t rgb) |
{ |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
450,17 → 461,25 |
{ |
switch (props->visual) { |
case VISUAL_INDIRECT_8: |
rgb_conv = rgb_323; |
rgb_conv = bgr_323; |
pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
rgb_conv = rgb_555; |
case VISUAL_RGB_5_5_5_LE: |
rgb_conv = rgb_555_le; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
rgb_conv = rgb_565; |
case VISUAL_RGB_5_5_5_BE: |
rgb_conv = rgb_555_be; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_LE: |
rgb_conv = rgb_565_le; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_BE: |
rgb_conv = rgb_565_be; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
rgb_conv = rgb_888; |
pixelbytes = 3; |
470,7 → 489,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: |
481,6 → 500,10 |
rgb_conv = bgr_0888; |
pixelbytes = 4; |
break; |
case VISUAL_BGR_8_8_8_0: |
rgb_conv = bgr_8880; |
pixelbytes = 4; |
break; |
default: |
panic("Unsupported visual."); |
} |
/branches/network/kernel/genarch/src/mm/page_ht.c |
---|
192,6 → 192,8 |
t->k = !(flags & PAGE_USER); |
t->c = (flags & PAGE_CACHEABLE) != 0; |
t->p = !(flags & PAGE_NOT_PRESENT); |
t->a = false; |
t->d = false; |
t->as = as; |
t->page = ALIGN_DOWN(page, PAGE_SIZE); |
/branches/network/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); |
} |
/** @} |
*/ |
/branches/network/kernel/genarch/src/drivers/via-cuda/cuda.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Martin Decky |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
38,16 → 39,53 |
#include <arch/asm.h> |
#include <mm/slab.h> |
#include <ddi/device.h> |
#include <synch/spinlock.h> |
static irq_ownership_t cuda_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
static irq_ownership_t cuda_claim(irq_t *irq); |
static void cuda_irq_handler(irq_t *irq); |
static void cuda_irq_handler(irq_t *irq) |
{ |
} |
static void cuda_irq_listen(irq_t *irq); |
static void cuda_irq_receive(irq_t *irq); |
static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len); |
static void cuda_irq_send_start(irq_t *irq); |
static void cuda_irq_send(irq_t *irq); |
static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *buf, size_t len); |
static void cuda_send_start(cuda_instance_t *instance); |
static void cuda_autopoll_set(cuda_instance_t *instance, bool enable); |
/** B register fields */ |
enum { |
TREQ = 0x08, |
TACK = 0x10, |
TIP = 0x20 |
}; |
/** IER register fields */ |
enum { |
IER_CLR = 0x00, |
IER_SET = 0x80, |
SR_INT = 0x04, |
ALL_INT = 0x7f |
}; |
/** ACR register fields */ |
enum { |
SR_OUT = 0x10 |
}; |
/** Packet types */ |
enum { |
PT_ADB = 0x00, |
PT_CUDA = 0x01 |
}; |
/** CUDA packet types */ |
enum { |
CPT_AUTOPOLL = 0x01 |
}; |
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
cuda_instance_t *instance |
55,7 → 93,15 |
if (instance) { |
instance->cuda = dev; |
instance->kbrdin = NULL; |
instance->xstate = cx_listen; |
instance->bidx = 0; |
instance->snd_bytes = 0; |
spinlock_initialize(&instance->dev_lock, "cuda_dev"); |
/* Disable all interrupts from CUDA. */ |
pio_write_8(&dev->ier, IER_CLR | ALL_INT); |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
64,15 → 110,251 |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
instance->irq.preack = true; |
} |
return instance; |
} |
#include <print.h> |
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin) |
{ |
cuda_t *dev = instance->cuda; |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
/* Enable SR interrupt. */ |
pio_write_8(&dev->ier, TIP | TREQ); |
pio_write_8(&dev->ier, IER_SET | SR_INT); |
/* Enable ADB autopolling. */ |
cuda_autopoll_set(instance, true); |
} |
static irq_ownership_t cuda_claim(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
uint8_t ifr; |
spinlock_lock(&instance->dev_lock); |
ifr = pio_read_8(&dev->ifr); |
spinlock_unlock(&instance->dev_lock); |
if ((ifr & SR_INT) == 0) |
return IRQ_DECLINE; |
return IRQ_ACCEPT; |
} |
static void cuda_irq_handler(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
uint8_t rbuf[CUDA_RCV_BUF_SIZE]; |
size_t len; |
bool handle; |
handle = false; |
len = 0; |
spinlock_lock(&instance->dev_lock); |
/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */ |
pio_write_8(&instance->cuda->ifr, SR_INT); |
switch (instance->xstate) { |
case cx_listen: cuda_irq_listen(irq); break; |
case cx_receive: cuda_irq_receive(irq); break; |
case cx_rcv_end: cuda_irq_rcv_end(irq, rbuf, &len); |
handle = true; break; |
case cx_send_start: cuda_irq_send_start(irq); break; |
case cx_send: cuda_irq_send(irq); break; |
} |
spinlock_unlock(&instance->dev_lock); |
/* Handle an incoming packet. */ |
if (handle) |
cuda_packet_handle(instance, rbuf, len); |
} |
/** Interrupt in listen state. |
* |
* Start packet reception. |
*/ |
static void cuda_irq_listen(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
uint8_t b; |
b = pio_read_8(&dev->b); |
if ((b & TREQ) != 0) { |
printf("cuda_irq_listen: no TREQ?!\n"); |
return; |
} |
pio_read_8(&dev->sr); |
pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP); |
instance->xstate = cx_receive; |
} |
/** Interrupt in receive state. |
* |
* Receive next byte of packet. |
*/ |
static void cuda_irq_receive(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
uint8_t b, data; |
data = pio_read_8(&dev->sr); |
if (instance->bidx < CUDA_RCV_BUF_SIZE) |
instance->rcv_buf[instance->bidx++] = data; |
b = pio_read_8(&dev->b); |
if ((b & TREQ) == 0) { |
pio_write_8(&dev->b, b ^ TACK); |
} else { |
pio_write_8(&dev->b, b | TACK | TIP); |
instance->xstate = cx_rcv_end; |
} |
} |
/** Interrupt in rcv_end state. |
* |
* Terminate packet reception. Either go back to listen state or start |
* receiving another packet if CUDA has one for us. |
*/ |
static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
uint8_t data, b; |
b = pio_read_8(&dev->b); |
data = pio_read_8(&dev->sr); |
if ((b & TREQ) == 0) { |
instance->xstate = cx_receive; |
pio_write_8(&dev->b, b & ~TIP); |
} else { |
instance->xstate = cx_listen; |
cuda_send_start(instance); |
} |
memcpy(buf, instance->rcv_buf, instance->bidx); |
*len = instance->bidx; |
instance->bidx = 0; |
} |
/** Interrupt in send_start state. |
* |
* Process result of sending first byte (and send second on success). |
*/ |
static void cuda_irq_send_start(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
uint8_t b; |
b = pio_read_8(&dev->b); |
if ((b & TREQ) == 0) { |
/* Collision */ |
pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT); |
pio_read_8(&dev->sr); |
pio_write_8(&dev->b, pio_read_8(&dev->b) | TIP | TACK); |
instance->xstate = cx_listen; |
return; |
} |
pio_write_8(&dev->sr, instance->snd_buf[1]); |
pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK); |
instance->bidx = 2; |
instance->xstate = cx_send; |
} |
/** Interrupt in send state. |
* |
* Send next byte or terminate transmission. |
*/ |
static void cuda_irq_send(irq_t *irq) |
{ |
cuda_instance_t *instance = irq->instance; |
cuda_t *dev = instance->cuda; |
if (instance->bidx < instance->snd_bytes) { |
/* Send next byte. */ |
pio_write_8(&dev->sr, instance->snd_buf[instance->bidx++]); |
pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK); |
return; |
} |
/* End transfer. */ |
instance->snd_bytes = 0; |
instance->bidx = 0; |
pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT); |
pio_read_8(&dev->sr); |
pio_write_8(&dev->b, pio_read_8(&dev->b) | TACK | TIP); |
instance->xstate = cx_listen; |
/* TODO: Match reply with request. */ |
} |
static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *data, size_t len) |
{ |
if (data[0] != 0x00 || data[1] != 0x40 || (data[2] != 0x2c |
&& data[2] != 0x8c)) |
return; |
/* The packet contains one or two scancodes. */ |
if (data[3] != 0xff) |
indev_push_character(instance->kbrdin, data[3]); |
if (data[4] != 0xff) |
indev_push_character(instance->kbrdin, data[4]); |
} |
static void cuda_autopoll_set(cuda_instance_t *instance, bool enable) |
{ |
instance->snd_buf[0] = PT_CUDA; |
instance->snd_buf[1] = CPT_AUTOPOLL; |
instance->snd_buf[2] = enable ? 0x01 : 0x00; |
instance->snd_bytes = 3; |
instance->bidx = 0; |
cuda_send_start(instance); |
} |
static void cuda_send_start(cuda_instance_t *instance) |
{ |
cuda_t *dev = instance->cuda; |
ASSERT(instance->xstate == cx_listen); |
if (instance->snd_bytes == 0) |
return; |
/* Check for incoming data. */ |
if ((pio_read_8(&dev->b) & TREQ) == 0) |
return; |
pio_write_8(&dev->acr, pio_read_8(&dev->acr) | SR_OUT); |
pio_write_8(&dev->sr, instance->snd_buf[0]); |
pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP); |
instance->xstate = cx_send_start; |
} |
/** @} |
*/ |
/branches/network/kernel/generic/include/string.h |
---|
88,7 → 88,7 |
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n); |
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); |
extern const char *str_chr(const char *str, wchar_t ch); |
extern char *str_chr(const char *str, wchar_t ch); |
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); |
extern bool wstr_remove(wchar_t *str, size_t pos); |
/branches/network/kernel/generic/include/context.h |
---|
45,7 → 45,7 |
(c)->sp = ((uintptr_t) (stack)) + (size) - SP_DELTA; |
#endif /* context_set */ |
extern int context_save_arch(context_t *c); |
extern int context_save_arch(context_t *c) __attribute__ ((returns_twice)); |
extern void context_restore_arch(context_t *c) __attribute__ ((noreturn)); |
/** Save register context. |
76,10 → 76,6 |
* corresponding call to context_save(), the only |
* difference being return value. |
* |
* Note that content of any local variable defined by |
* the caller of context_save() is undefined after |
* context_restore(). |
* |
* @param c Context structure. |
*/ |
static inline void context_restore(context_t *c) |
/branches/network/kernel/generic/src/main/uinit.c |
---|
79,6 → 79,14 |
uarg.uspace_thread_arg = NULL; |
free((uspace_arg_t *) arg); |
/* |
* Disable interrupts so that the execution of userspace() is not |
* disturbed by any interrupts as some of the userspace() |
* implementations will switch to the userspace stack before switching |
* the mode. |
*/ |
(void) interrupts_disable(); |
userspace(&uarg); |
} |
/branches/network/kernel/generic/src/lib/string.c |
---|
637,7 → 637,7 |
* @return Pointer to character in @a str or NULL if not found. |
* |
*/ |
const char *str_chr(const char *str, wchar_t ch) |
char *str_chr(const char *str, wchar_t ch) |
{ |
wchar_t acc; |
size_t off = 0; |
645,7 → 645,7 |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + last); |
return (char *) (str + last); |
last = off; |
} |
/branches/network/kernel/generic/src/ipc/event.c |
---|
140,9 → 140,11 |
IPC_SET_ARG4(call->data, a4); |
IPC_SET_ARG5(call->data, a5); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&events[evno].answerbox->irq_lock); |
list_append(&call->link, &events[evno].answerbox->irq_notifs); |
spinlock_unlock(&events[evno].answerbox->irq_lock); |
interrupts_restore(ipl); |
waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST); |
} |
/branches/network/kernel/arch/sparc64/include/atomic.h |
---|
123,7 → 123,7 |
"ldx %0, %2\n" |
"brz %2, 0b\n" |
"nop\n" |
"ba %xcc, 1b\n" |
"ba %%xcc, 1b\n" |
"nop\n" |
"2:\n" |
: "+m" (*((uint64_t *) x)), "+r" (tmp1), "+r" (tmp2) : "r" (0) |
/branches/network/kernel/arch/sparc64/include/context.h |
---|
39,7 → 39,7 |
#include <arch/types.h> |
#include <align.h> |
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE |
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE) |
#ifdef context_set |
#undef context_set |
/branches/network/kernel/arch/sparc64/src/asm.S |
---|
277,7 → 277,7 |
*/ |
.global switch_to_userspace |
switch_to_userspace: |
save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp |
save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp |
flushw |
wrpr %g0, 0, %cleanwin ! avoid information leak |
/branches/network/kernel/arch/sparc64/src/drivers/scr.c |
---|
133,11 → 133,11 |
break; |
case 16: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
visual = VISUAL_RGB_5_6_5; |
visual = VISUAL_RGB_5_6_5_BE; |
break; |
case 24: |
fb_scanline = fb_linebytes * 4; |
visual = VISUAL_RGB_8_8_8_0; |
visual = VISUAL_BGR_8_8_8_0; |
break; |
case 32: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
177,11 → 177,11 |
break; |
case 16: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
visual = VISUAL_RGB_5_6_5; |
visual = VISUAL_RGB_5_6_5_BE; |
break; |
case 24: |
fb_scanline = fb_linebytes * 4; |
visual = VISUAL_RGB_8_8_8_0; |
visual = VISUAL_BGR_8_8_8_0; |
break; |
case 32: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
/branches/network/kernel/arch/ia64/include/atomic.h |
---|
52,12 → 52,12 |
return v; |
} |
static inline uint64_t test_and_set(atomic_t *val) { |
static inline uint64_t test_and_set(atomic_t *val) |
{ |
uint64_t v; |
asm volatile ( |
"movl %0 = 0x01;;\n" |
"movl %0 = 0x1;;\n" |
"xchg8 %0 = %1, %0;;\n" |
: "=r" (v), "+m" (val->count) |
); |
65,6 → 65,13 |
return v; |
} |
static inline void atomic_lock_arch(atomic_t *val) |
{ |
do { |
while (val->count) |
; |
} while (test_and_set(val)); |
} |
static inline void atomic_inc(atomic_t *val) |
{ |
/branches/network/kernel/arch/ia64/include/mm/tlb.h |
---|
92,6 → 92,7 |
extern void data_dirty_bit_fault(uint64_t vector, istate_t *istate); |
extern void instruction_access_bit_fault(uint64_t vector, istate_t *istate); |
extern void data_access_bit_fault(uint64_t vector, istate_t *istate); |
extern void data_access_rights_fault(uint64_t vector, istate_t *istate); |
extern void page_not_present(uint64_t vector, istate_t *istate); |
#endif |
/branches/network/kernel/arch/ia64/src/ivt.S |
---|
536,7 → 536,7 |
HEAVYWEIGHT_HANDLER 0x5000 page_not_present |
HEAVYWEIGHT_HANDLER 0x5100 |
HEAVYWEIGHT_HANDLER 0x5200 |
HEAVYWEIGHT_HANDLER 0x5300 |
HEAVYWEIGHT_HANDLER 0x5300 data_access_rights_fault |
HEAVYWEIGHT_HANDLER 0x5400 general_exception |
HEAVYWEIGHT_HANDLER 0x5500 disabled_fp_register |
HEAVYWEIGHT_HANDLER 0x5600 |
/branches/network/kernel/arch/ia64/src/mm/tlb.c |
---|
710,6 → 710,37 |
page_table_unlock(AS, true); |
} |
/** Data access rights fault handler. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void data_access_rights_fault(uint64_t vector, istate_t *istate) |
{ |
region_register rr; |
rid_t rid; |
uintptr_t va; |
pte_t *t; |
va = istate->cr_ifa; /* faulting address */ |
rr.word = rr_read(VA2VRN(va)); |
rid = rr.map.rid; |
/* |
* Assume a write to a read-only page. |
*/ |
page_table_lock(AS, true); |
t = page_mapping_find(AS, va); |
ASSERT(t && t->p); |
ASSERT(!t->w); |
if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate, "Page fault at %p.", va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
page_table_unlock(AS, true); |
} |
/** Page not present fault handler. |
* |
* @param vector Interruption vector. |
/branches/network/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 |
/branches/network/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 |
/** @} |
*/ |
/branches/network/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_MACHINE_H_ |
#define KERN_arm32_MACHINE_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 |
/** @} |
*/ |
/branches/network/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_MACHINE_H_ |
#define KERN_arm32_MACHINE_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 |
/** @} |
*/ |
/branches/network/kernel/arch/arm32/include/drivers/gxemul.h |
---|
File deleted |
/branches/network/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,16 |
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 |
endif |
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 |
/branches/network/kernel/arch/arm32/src/exception.c |
---|
39,10 → 39,17 |
#include <interrupt.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <arch/drivers/gxemul.h> |
#include <print.h> |
#include <syscall/syscall.h> |
#ifdef MACHINE_testarm |
#include <arch/mach/testarm/testarm.h> |
#endif |
#ifdef MACHINE_integratorcp |
#include <arch/mach/integratorcp/integratorcp.h> |
#endif |
/** Offset used in calculation of exception handler's relative address. |
* |
* @see install_handler() |
58,159 → 65,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 → 86,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 → 96,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 → 142,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 |
/branches/network/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 |
/branches/network/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() |
{ |
} |
/** @} |
*/ |
/branches/network/kernel/arch/arm32/src/arm32.c |
---|
37,13 → 37,9 |
#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 <print.h> |
#include <config.h> |
#include <interrupt.h> |
52,6 → 48,15 |
#include <macros.h> |
#include <string.h> |
#ifdef MACHINE_testarm |
#include <arch/mach/testarm/testarm.h> |
#endif |
#ifdef MACHINE_integratorcp |
#include <arch/mach/integratorcp/integratorcp.h> |
#endif |
/** Performs arm32-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo) |
{ |
77,7 → 82,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 → 89,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 → 123,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 → 141,7 |
{ |
uint8_t *stck; |
tlb_invalidate_all(); |
stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]; |
supervisor_sp = (uintptr_t) stck; |
} |
183,8 → 157,7 |
/** Halts CPU. */ |
void cpu_halt(void) |
{ |
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET)) |
= 0; |
machine_cpu_halt(); |
} |
/** Reboot. */ |
211,6 → 184,7 |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
machine_grab_console(); |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
219,6 → 193,7 |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
machine_release_console(); |
} |
/** @} |
/branches/network/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_RGB_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 |
/branches/network/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_BGR_0_8_8_8, |
}; |
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); |
} |
/** @} |
*/ |
/branches/network/kernel/arch/arm32/src/mm/frame.c |
---|
35,9 → 35,16 |
#include <mm/frame.h> |
#include <arch/mm/frame.h> |
#include <arch/drivers/gxemul.h> |
#include <config.h> |
#ifdef MACHINE_testarm |
#include <arch/mach/testarm/testarm.h> |
#endif |
#ifdef MACHINE_integratorcp |
#include <arch/mach/integratorcp/integratorcp.h> |
#endif |
/** Address of the last frame in the memory. */ |
uintptr_t last_frame = 0; |
44,7 → 51,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 → 60,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. */ |
/branches/network/kernel/arch/arm32/src/interrupt.c |
---|
35,16 → 35,21 |
#include <arch/asm.h> |
#include <arch/regutils.h> |
#include <arch/drivers/gxemul.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <interrupt.h> |
#ifdef MACHINE_testarm |
#include <arch/mach/testarm/testarm.h> |
#endif |
#ifdef MACHINE_integratorcp |
#include <arch/mach/integratorcp/integratorcp.h> |
#endif |
/** 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 → 96,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 → 102,7 |
void interrupt_init(void) |
{ |
irq_init(IRQ_COUNT, IRQ_COUNT); |
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); |
machine_timer_irq_start(); |
} |
/** @} |
/branches/network/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 |
/branches/network/kernel/arch/arm32/src/drivers/gxemul.c |
---|
File deleted |
/branches/network/kernel/arch/ppc32/src/ppc32.c |
---|
36,6 → 36,7 |
#include <arch.h> |
#include <arch/boot/boot.h> |
#include <genarch/drivers/via-cuda/cuda.h> |
#include <genarch/kbrd/kbrd.h> |
#include <arch/interrupt.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
91,10 → 92,10 |
visual = VISUAL_INDIRECT_8; |
break; |
case 16: |
visual = VISUAL_RGB_5_5_5; |
visual = VISUAL_RGB_5_5_5_BE; |
break; |
case 24: |
visual = VISUAL_RGB_8_8_8; |
visual = VISUAL_BGR_8_8_8; |
break; |
case 32: |
visual = VISUAL_RGB_0_8_8_8; |
117,6 → 118,21 |
/* Initialize IRQ routing */ |
irq_init(IRQ_COUNT, IRQ_COUNT); |
/* Merge all zones to 1 big zone */ |
zone_merge_all(); |
} |
} |
void arch_post_cpu_init(void) |
{ |
} |
void arch_pre_smp_init(void) |
{ |
} |
void arch_post_smp_init(void) |
{ |
if (bootinfo.macio.addr) { |
/* Initialize PIC */ |
cir_t cir; |
123,7 → 139,7 |
void *cir_arg; |
pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg); |
#ifdef CONFIG_VIA_CUDA |
#ifdef CONFIG_MAC_KBD |
uintptr_t pa = bootinfo.macio.addr + 0x16000; |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
136,29 → 152,18 |
cuda_instance_t *cuda_instance = |
cuda_init(cuda, IRQ_CUDA, cir, cir_arg); |
if (cuda_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
cuda_wire(cuda_instance, sink); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
cuda_wire(cuda_instance, kbrd); |
pic_enable_interrupt(IRQ_CUDA); |
} |
} |
#endif |
} |
/* Merge all zones to 1 big zone */ |
zone_merge_all(); |
} |
} |
void arch_post_cpu_init(void) |
{ |
} |
void arch_pre_smp_init(void) |
{ |
} |
void arch_post_smp_init(void) |
{ |
} |
void calibrate_delay_loop(void) |
{ |
} |
/branches/network/kernel/arch/mips32/include/context_offset.h |
---|
86,7 → 86,7 |
#define EOFFSET_STATUS 0x58 |
#define EOFFSET_EPC 0x5c |
#define EOFFSET_K1 0x60 |
#define REGISTER_SPACE 100 |
#define REGISTER_SPACE 104 /* respect stack alignment */ |
#ifdef __ASM__ |
/branches/network/kernel/arch/mips32/include/atomic.h |
---|
88,6 → 88,13 |
return v; |
} |
static inline void atomic_lock_arch(atomic_t *val) { |
do { |
while (val->count) |
; |
} while (test_and_set(val)); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/mips32/src/mips32.c |
---|
141,7 → 141,7 |
.x = 640, |
.y = 480, |
.scan = 1920, |
.visual = VISUAL_BGR_8_8_8, |
.visual = VISUAL_RGB_8_8_8, |
}; |
fb_init(&gxemul_prop); |
#else |
/branches/network/kernel/arch/ia32/src/drivers/vesa.c |
---|
85,15 → 85,15 |
if ((vesa_red_mask == 5) && (vesa_red_pos == 10) |
&& (vesa_green_mask == 5) && (vesa_green_pos == 5) |
&& (vesa_blue_mask == 5) && (vesa_blue_pos == 0)) |
visual = VISUAL_RGB_5_5_5; |
visual = VISUAL_RGB_5_5_5_LE; |
else |
visual = VISUAL_RGB_5_6_5; |
visual = VISUAL_RGB_5_6_5_LE; |
break; |
case 24: |
visual = VISUAL_RGB_8_8_8; |
visual = VISUAL_BGR_8_8_8; |
break; |
case 32: |
visual = VISUAL_RGB_0_8_8_8; |
visual = VISUAL_BGR_8_8_8_0; |
break; |
default: |
panic("Unsupported bits per pixel."); |
/branches/network/uspace/app/bdsh/cmds/modules/cp/cp.c |
---|
172,7 → 172,8 |
int cmd_cp(char **argv) |
{ |
unsigned int argc, buffer = 0, verbose = 0; |
unsigned int argc, verbose = 0; |
int buffer = 0; |
int c, opt_ind; |
int64_t ret; |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
209,7 → 209,7 |
} |
} |
if (optind == argc) { |
if ((unsigned) optind == argc) { |
cli_error(CL_EFAIL, |
"%s: insufficient arguments. Try %s --help", cmdname, cmdname); |
rm_end(&rm); |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
50,48 → 50,9 |
static char *cmdname = "ls"; |
static inline off_t flen(const char *f) |
{ |
int fd; |
off_t size; |
fd = open(f, O_RDONLY); |
if (fd == -1) |
return 0; |
size = lseek(fd, 0, SEEK_END); |
close(fd); |
if (size < 0) |
size = 0; |
return size; |
} |
static unsigned int ls_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return LS_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return LS_FILE; |
} |
return LS_BOGUS; |
} |
static void ls_scan_dir(const char *d, DIR *dirp) |
{ |
struct dirent *dp; |
unsigned int scope; |
char *buff; |
if (! dirp) |
108,21 → 69,8 |
/* Don't worry if inserting a double slash, this will be fixed by |
* absolutize() later with subsequent calls to open() or readdir() */ |
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_DIR: |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name, buff); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
* it and the time that it was scoped */ |
printf("ls: skipping bogus node %s\n", dp->d_name); |
break; |
ls_print(dp->d_name, buff); |
} |
} |
free(buff); |
129,7 → 77,7 |
return; |
} |
/* ls_print_* currently does nothing more than print the entry. |
/* ls_print currently does nothing more than print the entry. |
* in the future, we will likely pass the absolute path, and |
* some sort of ls_options structure that controls how each |
* entry is printed and what is printed about it. |
136,16 → 84,23 |
* |
* Now we just print basic DOS style lists */ |
static void ls_print_dir(const char *d) |
static void ls_print(const char *name, const char *pathname) |
{ |
printf("%-40s\t<dir>\n", d); |
struct stat s; |
int rc; |
rc = stat(pathname, &s); |
if (rc != 0) { |
/* Odd chance it was deleted from the time readdir() found it */ |
printf("ls: skipping bogus node %s\n", pathname); |
printf("rc=%d\n", rc); |
return; |
} |
static void ls_print_file(const char *name, const char *pathname) |
{ |
printf("%-40s\t%llu\n", name, (long long) flen(pathname)); |
if (s.is_file) |
printf("%-40s\t%llu\n", name, (long long) s.size); |
else |
printf("%-40s\n", name); |
return; |
} |
166,7 → 121,7 |
int cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
struct stat s; |
char *buff; |
DIR *dirp; |
184,17 → 139,15 |
else |
str_cpy(buff, PATH_MAX, argv[1]); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_BOGUS: |
if (stat(buff, &s)) { |
cli_error(CL_ENOENT, buff); |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff, buff); |
break; |
case LS_DIR: |
} |
if (s.is_file) { |
ls_print(buff, buff); |
} else { |
dirp = opendir(buff); |
if (! dirp) { |
/* May have been deleted between scoping it and opening it */ |
204,7 → 157,6 |
} |
ls_scan_dir(buff, dirp); |
closedir(dirp); |
break; |
} |
free(buff); |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
6,11 → 6,8 |
#define LS_FILE 1 |
#define LS_DIR 2 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *, const char *); |
static void ls_print(const char *, const char *); |
#endif /* LS_H */ |
/branches/network/uspace/app/bdsh/util.c |
---|
53,14 → 53,6 |
* string */ |
unsigned int cli_set_prompt(cliuser_t *usr) |
{ |
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX); |
if (NULL == usr->prompt) { |
cli_error(CL_ENOMEM, "Can not allocate prompt"); |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->prompt, 0, sizeof(usr->prompt)); |
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX); |
if (NULL == usr->cwd) { |
cli_error(CL_ENOMEM, "Can not allocate cwd"); |
67,13 → 59,11 |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->cwd, 0, sizeof(usr->cwd)); |
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1); |
if (NULL == usr->cwd) |
if (!getcwd(usr->cwd, PATH_MAX)) |
snprintf(usr->cwd, PATH_MAX, "(unknown)"); |
if (usr->prompt) |
free(usr->prompt); |
asprintf(&usr->prompt, "%s # ", usr->cwd); |
return 0; |
/branches/network/uspace/app/bdsh/exec.c |
---|
112,7 → 112,9 |
unsigned int try_exec(char *cmd, char **argv) |
{ |
task_id_t tid; |
task_exit_t texit; |
char *tmp; |
int retval; |
tmp = str_dup(find_command(cmd)); |
free(found); |
125,6 → 127,12 |
return 1; |
} |
task_wait(tid); |
task_wait(tid, &texit, &retval); |
if (texit != TASK_EXIT_NORMAL) { |
printf("Command failed (unexpectedly terminated).\n"); |
} else if (retval != 0) { |
printf("Command failed (return value %d).\n", retval); |
} |
return 0; |
} |
/branches/network/uspace/app/init/init.c |
---|
41,11 → 41,13 |
#include <bool.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#include <task.h> |
#include <malloc.h> |
#include <macros.h> |
#include <string.h> |
#include <devmap.h> |
#include <config.h> |
#include "init.h" |
static void info_print(void) |
55,7 → 57,6 |
static bool mount_root(const char *fstype) |
{ |
int rc = -1; |
char *opts = ""; |
const char *root_dev = "initrd"; |
62,8 → 63,7 |
if (str_cmp(fstype, "tmpfs") == 0) |
opts = "restore"; |
while (rc < 0) { |
rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING); |
int rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
72,7 → 72,7 |
break; |
case EBUSY: |
printf(NAME ": Root filesystem already mounted\n"); |
break; |
return false; |
case ELIMIT: |
printf(NAME ": Unable to mount root filesystem\n"); |
return false; |
79,8 → 79,10 |
case ENOENT: |
printf(NAME ": Unknown filesystem type (%s)\n", fstype); |
return false; |
default: |
printf(NAME ": Error mounting root filesystem (%d)\n", rc); |
return false; |
} |
} |
return true; |
} |
87,11 → 89,17 |
static bool mount_devfs(void) |
{ |
int rc = -1; |
char null[MAX_DEVICE_NAME]; |
int null_id = devmap_null_create(); |
while (rc < 0) { |
rc = mount("devfs", "/dev", "null", "", IPC_FLAG_BLOCKING); |
if (null_id == -1) { |
printf(NAME ": Unable to create null device\n"); |
return false; |
} |
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id); |
int rc = mount("devfs", "/dev", null, "", IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
printf(NAME ": Device filesystem mounted\n"); |
98,15 → 106,21 |
break; |
case EBUSY: |
printf(NAME ": Device filesystem already mounted\n"); |
break; |
devmap_null_destroy(null_id); |
return false; |
case ELIMIT: |
printf(NAME ": Unable to mount device filesystem\n"); |
devmap_null_destroy(null_id); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (devfs)\n"); |
devmap_null_destroy(null_id); |
return false; |
default: |
printf(NAME ": Error mounting device filesystem (%d)\n", rc); |
devmap_null_destroy(null_id); |
return false; |
} |
} |
return true; |
} |
114,7 → 128,11 |
static void spawn(char *fname) |
{ |
char *argv[2]; |
struct stat s; |
if (stat(fname, &s) == ENOENT) |
return; |
printf(NAME ": Spawning %s\n", fname); |
argv[0] = fname; |
124,6 → 142,40 |
printf(NAME ": Error spawning %s\n", fname); |
} |
static void srv_start(char *fname) |
{ |
char *argv[2]; |
task_id_t id; |
task_exit_t texit; |
int rc, retval; |
struct stat s; |
if (stat(fname, &s) == ENOENT) |
return; |
printf(NAME ": Starting %s\n", fname); |
argv[0] = fname; |
argv[1] = NULL; |
id = task_spawn(fname, argv); |
if (!id) { |
printf(NAME ": Error spawning %s\n", fname); |
return; |
} |
rc = task_wait(id, &texit, &retval); |
if (rc != EOK) { |
printf(NAME ": Error waiting for %s\n", fname); |
return; |
} |
if (texit != TASK_EXIT_NORMAL || retval != 0) { |
printf(NAME ": Server %s failed to start (returned %d)\n", |
fname, retval); |
} |
} |
static void getvc(char *dev, char *app) |
{ |
char *argv[4]; |
150,7 → 202,7 |
} |
} |
void mount_data(void) |
static void mount_data(void) |
{ |
int rc; |
186,11 → 238,23 |
spawn("/srv/console"); |
spawn("/srv/fhc"); |
spawn("/srv/obio"); |
spawn("/srv/ata_bd"); |
spawn("/srv/gxe_bd"); |
usleep(250000); |
/* |
* Start these synchronously so that mount_data() can be |
* non-blocking. |
*/ |
#ifdef CONFIG_START_BD |
srv_start("/srv/ata_bd"); |
srv_start("/srv/gxe_bd"); |
#else |
(void) srv_start; |
#endif |
#ifdef CONFIG_MOUNT_DATA |
mount_data(); |
#else |
(void) mount_data; |
#endif |
getvc("vc0", "/app/bdsh"); |
getvc("vc1", "/app/bdsh"); |
/branches/network/uspace/app/init/Makefile |
---|
34,6 → 34,7 |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../.. |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
/branches/network/uspace/app/tester/devmap/devmap1.def |
---|
File deleted |
/branches/network/uspace/app/tester/devmap/devmap1.c |
---|
File deleted |
/branches/network/uspace/app/tester/console/console1.c |
---|
46,10 → 46,9 |
[COLOR_WHITE] = "white" |
}; |
char * test_console1(bool quiet) |
char *test_console1(void) |
{ |
int i, j; |
if (!test_quiet) { |
printf("Style test: "); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
61,7 → 60,10 |
console_set_style(fphone(stdout), STYLE_NORMAL); |
printf(".\n"); |
printf("Foreground color test:\n"); |
unsigned int i; |
unsigned int j; |
printf("\nForeground color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
fflush(stdout); |
74,7 → 76,7 |
putchar('\n'); |
} |
printf("Background color test:\n"); |
printf("\nBackground color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
fflush(stdout); |
87,7 → 89,7 |
putchar('\n'); |
} |
printf("Now let's test RGB colors:\n"); |
printf("\nRGB colors test:\n"); |
for (i = 0; i < 255; i += 16) { |
fflush(stdout); |
115,9 → 117,7 |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
printf("[press a key]\n"); |
getchar(); |
return NULL; |
} |
/branches/network/uspace/app/tester/stdio/stdio1.c |
---|
32,54 → 32,59 |
#include "../tester.h" |
#define BUF_SIZE 32 |
static char buf[BUF_SIZE + 1]; |
char * test_stdio1(bool quiet) |
char *test_stdio1(void) |
{ |
FILE *f; |
FILE *file; |
char *file_name = "/readme"; |
size_t n; |
int c; |
printf("Open file '%s'\n", file_name); |
TPRINTF("Open file \"%s\"...", file_name); |
errno = 0; |
f = fopen(file_name, "rt"); |
file = fopen(file_name, "rt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
if (f == NULL) printf("errno = %d\n", errno); |
TPRINTF("Read file..."); |
size_t cnt = fread(buf, 1, BUF_SIZE, file); |
if (ferror(file)) { |
TPRINTF("errno = %d\n", errno); |
fclose(file); |
return "Failed reading file"; |
} else |
TPRINTF("OK\n"); |
if (f == NULL) |
return "Failed opening file."; |
buf[cnt] = '\0'; |
TPRINTF("Read %u bytes, string \"%s\"\n", cnt, buf); |
n = fread(buf, 1, BUF_SIZE, f); |
if (ferror(f)) { |
fclose(f); |
return "Failed reading file."; |
} |
TPRINTF("Seek to beginning..."); |
if (fseek(file, 0, SEEK_SET) != 0) { |
TPRINTF("errno = %d\n", errno); |
fclose(file); |
return "Failed seeking in file"; |
} else |
TPRINTF("OK\n"); |
printf("Read %d bytes.\n", n); |
buf[n] = '\0'; |
printf("Read string '%s'.\n", buf); |
printf("Seek to beginning.\n"); |
if (fseek(f, 0, SEEK_SET) != 0) { |
fclose(f); |
return "Failed seeking."; |
} |
printf("Read using fgetc().\n"); |
TPRINTF("Read using fgetc()..."); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
int c = fgetc(file); |
if (c == EOF) |
break; |
printf("'%c'", c); |
TPRINTF("."); |
} |
TPRINTF("[EOF]\n"); |
printf("[EOF]\n"); |
printf("Closing.\n"); |
TPRINTF("Close..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
if (fclose(f) != 0) |
return "Failed closing."; |
return NULL; |
} |
/branches/network/uspace/app/tester/stdio/stdio2.c |
---|
31,38 → 31,53 |
#include <errno.h> |
#include "../tester.h" |
char * test_stdio2(bool quiet) |
char *test_stdio2(void) |
{ |
FILE *f; |
FILE *file; |
char *file_name = "/test"; |
int c; |
printf("Open file '%s' for writing\n", file_name); |
TPRINTF("Open file \"%s\" for writing...", file_name); |
errno = 0; |
f = fopen(file_name, "wt"); |
file = fopen(file_name, "wt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
if (f == NULL) |
return "Failed opening file."; |
TPRINTF("Write to file..."); |
fprintf(file, "integer: %u, string: \"%s\"", 42, "Hello!"); |
TPRINTF("OK\n"); |
fprintf(f, "Integer: %d, string: '%s'\n", 42, "Hello!"); |
if (fclose(f) != 0) |
return "Failed closing file."; |
TPRINTF("Close..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
printf("Open file '%s' for reading\n", file_name); |
TPRINTF("Open file \"%s\" for reading...", file_name); |
file = fopen(file_name, "rt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
f = fopen(file_name, "rt"); |
if (f == NULL) |
return "Failed opening file."; |
printf("File contains:\n"); |
TPRINTF("File contains:\n"); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
putchar(c); |
int c = fgetc(file); |
if (c == EOF) |
break; |
TPRINTF("%c", c); |
} |
if (fclose(f) != 0) |
return "Failed closing file."; |
TPRINTF("\nClose..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
return NULL; |
} |
/branches/network/uspace/app/tester/tester.c |
---|
27,7 → 27,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup tester User space Tester |
/** @addtogroup tester User space tester |
* @brief User space testing infrastructure. |
* @{ |
*/ |
37,48 → 37,44 |
#include <unistd.h> |
#include <stdio.h> |
#include <string.h> |
#include "tester.h" |
int myservice = 0; |
int phones[MAX_PHONES]; |
int connections[MAX_CONNECTIONS]; |
ipc_callid_t callids[MAX_CONNECTIONS]; |
bool test_quiet; |
int test_argc; |
char **test_argv; |
test_t tests[] = { |
#include "thread/thread1.def" |
#include "print/print1.def" |
#include "print/print2.def" |
#include "print/print3.def" |
#include "print/print4.def" |
#include "console/console1.def" |
#include "stdio/stdio1.def" |
#include "stdio/stdio2.def" |
#include "fault/fault1.def" |
#include "fault/fault2.def" |
#include "vfs/vfs1.def" |
#include "ipc/ping_pong.def" |
#include "ipc/register.def" |
#include "ipc/connect.def" |
#include "ipc/send_async.def" |
#include "ipc/send_sync.def" |
#include "ipc/answer.def" |
#include "ipc/hangup.def" |
#include "ipc/ping_pong.def" |
#include "devmap/devmap1.def" |
#include "loop/loop1.def" |
#include "vfs/vfs1.def" |
#include "console/console1.def" |
#include "stdio/stdio1.def" |
#include "stdio/stdio2.def" |
{NULL, NULL, NULL} |
#include "mm/malloc1.def" |
{NULL, NULL, NULL, false} |
}; |
static bool run_test(test_t *test) |
{ |
printf("%s\t\t%s\n", test->name, test->desc); |
/* Execute the test */ |
char * ret = test->entry(false); |
char *ret = test->entry(); |
if (ret == NULL) { |
printf("Test passed\n\n"); |
printf("\nTest passed\n"); |
return true; |
} |
printf("%s\n\n", ret); |
printf("\n%s\n", ret); |
return false; |
} |
92,6 → 88,7 |
for (test = tests; test->name != NULL; test++) { |
if (test->safe) { |
printf("%s (%s)\n", test->name, test->desc); |
if (run_test(test)) |
i++; |
else |
99,63 → 96,51 |
} |
} |
printf("\nSafe tests completed, %u tests run, %u passed.\n\n", i + n, i); |
printf("\nCompleted, %u tests run, %u passed.\n", i + n, i); |
} |
static void list_tests(void) |
{ |
size_t len = 0; |
test_t *test; |
char c = 'a'; |
for (test = tests; test->name != NULL; test++) { |
if (str_length(test->name) > len) |
len = str_length(test->name); |
} |
for (test = tests; test->name != NULL; test++, c++) |
printf("%c\t%s\t\t%s%s\n", c, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
for (test = tests; test->name != NULL; test++) |
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("*\t\t\tRun all safe tests\n"); |
printf("%-*s Run all safe tests\n", len, "*"); |
} |
int main(int argc, char **argv) |
int main(int argc, char *argv[]) |
{ |
printf("Number of arguments: %d\n", argc); |
if (argv) { |
printf("Arguments:"); |
while (*argv) { |
printf(" '%s'", *argv++); |
if (argc < 2) { |
printf("Usage:\n\n"); |
printf("%s <test> [args ...]\n\n", argv[0]); |
list_tests(); |
return 0; |
} |
printf("\n"); |
} |
while (1) { |
char c; |
test_t *test; |
test_quiet = false; |
test_argc = argc - 2; |
test_argv = argv + 2; |
list_tests(); |
printf("> "); |
fflush(stdout); |
c = getchar(); |
printf("%c\n", c); |
if ((c >= 'a') && (c <= 'z')) { |
for (test = tests; test->name != NULL; test++, c--) |
if (c == 'a') |
break; |
if (test->name == NULL) |
printf("Unknown test\n\n"); |
else |
run_test(test); |
} else if (c == '*') { |
if (str_cmp(argv[1], "*") == 0) { |
run_safe_tests(); |
} else if (c < 0) { |
/* got EOF */ |
break; |
} else { |
printf("Invalid test\n\n"); |
return 0; |
} |
test_t *test; |
for (test = tests; test->name != NULL; test++) { |
if (str_cmp(argv[1], test->name) == 0) { |
return (run_test(test) ? 0 : -1); |
} |
} |
return 0; |
printf("Unknown test \"%s\"\n", argv[1]); |
return -2; |
} |
/** @} |
/branches/network/uspace/app/tester/thread/thread1.c |
---|
27,7 → 27,8 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#define THREADS 5 |
#define THREADS 20 |
#define DELAY 10 |
#include <atomic.h> |
#include <thread.h> |
37,45 → 38,42 |
static atomic_t finish; |
static atomic_t threads_finished; |
static bool sh_quiet; |
static void threadtest(void *data) |
{ |
thread_detach(thread_get_id()); |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", thread_get_id()); |
while (atomic_get(&finish)) |
usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
char * test_thread1(bool quiet) |
char *test_thread1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
unsigned int i; |
int total = 0; |
atomic_set(&finish, 1); |
atomic_set(&threads_finished, 0); |
TPRINTF("Creating threads"); |
for (i = 0; i < THREADS; i++) { |
if (thread_create(threadtest, NULL, "threadtest", NULL) < 0) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("\nCould not create thread %u\n", i); |
break; |
} |
TPRINTF("."); |
total++; |
} |
if (!quiet) |
printf("Running threads for 10 seconds...\n"); |
sleep(10); |
TPRINTF("\nRunning threads for %u seconds...", DELAY); |
sleep(DELAY); |
TPRINTF("\n"); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
TPRINTF("Threads left: %u\n", total - atomic_get(&threads_finished)); |
sleep(1); |
} |
/branches/network/uspace/app/tester/loop/loop1.c |
---|
30,12 → 30,11 |
#include <stdlib.h> |
#include "../tester.h" |
char *test_loop1(bool quiet) |
char *test_loop1(void) |
{ |
printf("Looping...\n"); |
while (1); |
printf("Survived endless loop?!!\n"); |
TPRINTF("Looping..."); |
while (true); |
TPRINTF("\n"); |
return NULL; |
return "Survived endless loop"; |
} |
/branches/network/uspace/app/tester/mm/malloc1.def |
---|
0,0 → 1,6 |
{ |
"malloc1", |
"Memory allocator test", |
&test_malloc1, |
true |
}, |
/branches/network/uspace/app/tester/mm/malloc1.c |
---|
0,0 → 1,651 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Tomas Bures |
* Copyright (c) 2009 Lubomir Bulej |
* 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. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <malloc.h> |
#include "../tester.h" |
/* |
* The test consists of several phases which differ in the size of blocks |
* they allocate. The size of blocks is given as a range of minimum and |
* maximum allowed size. Each of the phases is divided into 3 subphases which |
* differ in the probability of free and alloc actions. Second subphase is |
* started when malloc returns 'out of memory' or when MAX_ALLOC is reached. |
* Third subphase is started after a given number of cycles. The third subphase |
* as well as the whole phase ends when all memory blocks are released. |
*/ |
/** |
* sizeof_array |
* @array array to determine the size of |
* |
* Returns the size of @array in array elements. |
*/ |
#define sizeof_array(array) \ |
(sizeof(array) / sizeof((array)[0])) |
#define MAX_ALLOC (16 * 1024 * 1024) |
/* |
* Subphase control structures: subphase termination conditions, |
* probabilities of individual actions, subphase control structure. |
*/ |
typedef struct { |
unsigned int max_cycles; |
unsigned int no_memory; |
unsigned int no_allocated; |
} sp_term_cond_s; |
typedef struct { |
unsigned int alloc; |
unsigned int free; |
} sp_action_prob_s; |
typedef struct { |
char *name; |
sp_term_cond_s cond; |
sp_action_prob_s prob; |
} subphase_s; |
/* |
* Phase control structures: The minimum and maximum block size that |
* can be allocated during the phase execution, phase control structure. |
*/ |
typedef struct { |
size_t min_block_size; |
size_t max_block_size; |
} ph_alloc_size_s; |
typedef struct { |
char *name; |
ph_alloc_size_s alloc; |
subphase_s *subphases; |
} phase_s; |
/* |
* Subphases are defined separately here. This is for two reasons: |
* 1) data are not duplicated, 2) we don't have to state beforehand |
* how many subphases a phase contains. |
*/ |
static subphase_s subphases_32B[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 200, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_128K[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 70, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 30, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 30, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_default[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
/* |
* Phase definitions. |
*/ |
static phase_s phases[] = { |
{ |
.name = "32 B memory blocks", |
.alloc = { |
.min_block_size = 32, |
.max_block_size = 32 |
}, |
.subphases = subphases_32B |
}, |
{ |
.name = "128 KB memory blocks", |
.alloc = { |
.min_block_size = 128 * 1024, |
.max_block_size = 128 * 1024 |
}, |
.subphases = subphases_128K |
}, |
{ |
.name = "2500 B memory blocks", |
.alloc = { |
.min_block_size = 2500, |
.max_block_size = 2500 |
}, |
.subphases = subphases_default |
}, |
{ |
.name = "1 B .. 250000 B memory blocks", |
.alloc = { |
.min_block_size = 1, |
.max_block_size = 250000 |
}, |
.subphases = subphases_default |
} |
}; |
/* |
* Global error flag. The flag is set if an error |
* is encountered (overlapping blocks, inconsistent |
* block data, etc.) |
*/ |
static bool error_flag = false; |
/* |
* Memory accounting: the amount of allocated memory and the |
* number and list of allocated blocks. |
*/ |
static size_t mem_allocated; |
static size_t mem_blocks_count; |
static LIST_INITIALIZE(mem_blocks); |
typedef struct { |
/* Address of the start of the block */ |
void *addr; |
/* Size of the memory block */ |
size_t size; |
/* link to other blocks */ |
link_t link; |
} mem_block_s; |
typedef mem_block_s *mem_block_t; |
/** init_mem |
* |
* Initializes the memory accounting structures. |
* |
*/ |
static void init_mem(void) |
{ |
mem_allocated = 0; |
mem_blocks_count = 0; |
} |
static bool overlap_match(link_t *entry, void *addr, size_t size) |
{ |
mem_block_t mblk = list_get_instance(entry, mem_block_s, link); |
/* Entry block control structure <mbeg, mend) */ |
uint8_t *mbeg = (uint8_t *) mblk; |
uint8_t *mend = (uint8_t *) mblk + sizeof(mem_block_s); |
/* Entry block memory <bbeg, bend) */ |
uint8_t *bbeg = (uint8_t *) mblk->addr; |
uint8_t *bend = (uint8_t *) mblk->addr + mblk->size; |
/* Data block <dbeg, dend) */ |
uint8_t *dbeg = (uint8_t *) addr; |
uint8_t *dend = (uint8_t *) addr + size; |
/* Check for overlaps */ |
if (((mbeg >= dbeg) && (mbeg < dend)) || |
((mend > dbeg) && (mend <= dend)) || |
((bbeg >= dbeg) && (bbeg < dend)) || |
((bend > dbeg) && (bend <= dend))) |
return true; |
return false; |
} |
/** test_overlap |
* |
* Test whether a block starting at @addr overlaps with another, previously |
* allocated memory block or its control structure. |
* |
* @param addr Initial address of the block |
* @param size Size of the block |
* |
* @return false if the block does not overlap. |
* |
*/ |
static int test_overlap(void *addr, size_t size) |
{ |
link_t *entry; |
bool fnd = false; |
for (entry = mem_blocks.next; entry != &mem_blocks; entry = entry->next) { |
if (overlap_match(entry, addr, size)) { |
fnd = true; |
break; |
} |
} |
return fnd; |
} |
/** checked_malloc |
* |
* Allocate @size bytes of memory and check whether the chunk comes |
* from the non-mapped memory region and whether the chunk overlaps |
* with other, previously allocated, chunks. |
* |
* @param size Amount of memory to allocate |
* |
* @return NULL if the allocation failed. Sets the global error_flag to |
* true if the allocation succeeded but is illegal. |
* |
*/ |
static void *checked_malloc(size_t size) |
{ |
void *data; |
/* Allocate the chunk of memory */ |
data = malloc(size); |
if (data == NULL) |
return NULL; |
/* Check for overlaps with other chunks */ |
if (test_overlap(data, size)) { |
TPRINTF("\nError: Allocated block overlaps with another " |
"previously allocated block.\n"); |
error_flag = true; |
} |
return data; |
} |
/** alloc_block |
* |
* Allocate a block of memory of @size bytes and add record about it into |
* the mem_blocks list. Return a pointer to the block holder structure or |
* NULL if the allocation failed. |
* |
* If the allocation is illegal (e.g. the memory does not come from the |
* right region or some of the allocated blocks overlap with others), |
* set the global error_flag. |
* |
* @param size Size of the memory block |
* |
*/ |
static mem_block_t alloc_block(size_t size) |
{ |
/* Check for allocation limit */ |
if (mem_allocated >= MAX_ALLOC) |
return NULL; |
/* Allocate the block holder */ |
mem_block_t block = (mem_block_t) checked_malloc(sizeof(mem_block_s)); |
if (block == NULL) |
return NULL; |
link_initialize(&block->link); |
/* Allocate the block memory */ |
block->addr = checked_malloc(size); |
if (block->addr == NULL) { |
free(block); |
return NULL; |
} |
block->size = size; |
/* Register the allocated block */ |
list_append(&block->link, &mem_blocks); |
mem_allocated += size + sizeof(mem_block_s); |
mem_blocks_count++; |
return block; |
} |
/** free_block |
* |
* Free the block of memory and the block control structure allocated by |
* alloc_block. Set the global error_flag if an error occurs. |
* |
* @param block Block control structure |
* |
*/ |
static void free_block(mem_block_t block) |
{ |
/* Unregister the block */ |
list_remove(&block->link); |
mem_allocated -= block->size + sizeof(mem_block_s); |
mem_blocks_count--; |
/* Free the memory */ |
free(block->addr); |
free(block); |
} |
/** expected_value |
* |
* Compute the expected value of a byte located at @pos in memory |
* block described by @blk. |
* |
* @param blk Memory block control structure |
* @param pos Position in the memory block data area |
* |
*/ |
static inline uint8_t expected_value(mem_block_t blk, uint8_t *pos) |
{ |
return ((unsigned long) blk ^ (unsigned long) pos) & 0xff; |
} |
/** fill_block |
* |
* Fill the memory block controlled by @blk with data. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void fill_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) |
*pos = expected_value(blk, pos); |
} |
/** check_block |
* |
* Check whether the block @blk contains the data it was filled with. |
* Set global error_flag if an error occurs. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void check_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) { |
if (*pos != expected_value (blk, pos)) { |
TPRINTF("\nError: Corrupted content of a data block.\n"); |
error_flag = true; |
return; |
} |
} |
} |
static link_t *list_get_nth(link_t *list, unsigned int i) |
{ |
unsigned int cnt = 0; |
link_t *entry; |
for (entry = list->next; entry != list; entry = entry->next) { |
if (cnt == i) |
return entry; |
cnt++; |
} |
return NULL; |
} |
/** get_random_block |
* |
* Select a random memory block from the list of allocated blocks. |
* |
* @return Block control structure or NULL if the list is empty. |
* |
*/ |
static mem_block_t get_random_block(void) |
{ |
if (mem_blocks_count == 0) |
return NULL; |
unsigned int blkidx = rand() % mem_blocks_count; |
link_t *entry = list_get_nth(&mem_blocks, blkidx); |
if (entry == NULL) { |
TPRINTF("\nError: Corrupted list of allocated memory blocks.\n"); |
error_flag = true; |
} |
return list_get_instance(entry, mem_block_s, link); |
} |
#define RETURN_IF_ERROR \ |
{ \ |
if (error_flag) \ |
return; \ |
} |
static void do_subphase(phase_s *phase, subphase_s *subphase) |
{ |
unsigned int cycles; |
for (cycles = 0; /* always */; cycles++) { |
if (subphase->cond.max_cycles && |
cycles >= subphase->cond.max_cycles) { |
/* |
* We have performed the required number of |
* cycles. End the current subphase. |
*/ |
break; |
} |
/* |
* Decide whether we alloc or free memory in this step. |
*/ |
unsigned int rnd = rand() % 100; |
if (rnd < subphase->prob.alloc) { |
/* Compute a random number lying in interval <min_block_size, max_block_size> */ |
int alloc = phase->alloc.min_block_size + |
(rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1)); |
mem_block_t blk = alloc_block(alloc); |
RETURN_IF_ERROR; |
if (blk == NULL) { |
TPRINTF("F(A)"); |
if (subphase->cond.no_memory) { |
/* We filled the memory. Proceed to next subphase */ |
break; |
} |
} else { |
TPRINTF("A"); |
fill_block(blk); |
} |
} else if (rnd < subphase->prob.free) { |
mem_block_t blk = get_random_block(); |
if (blk == NULL) { |
TPRINTF("F(R)"); |
if (subphase->cond.no_allocated) { |
/* We free all the memory. Proceed to next subphase. */ |
break; |
} |
} else { |
TPRINTF("R"); |
check_block(blk); |
RETURN_IF_ERROR; |
free_block(blk); |
RETURN_IF_ERROR; |
} |
} |
} |
TPRINTF("\n.. finished.\n"); |
} |
static void do_phase(phase_s *phase) |
{ |
unsigned int subno; |
for (subno = 0; subno < 3; subno++) { |
subphase_s *subphase = & phase->subphases [subno]; |
TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name); |
do_subphase(phase, subphase); |
RETURN_IF_ERROR; |
} |
} |
char *test_malloc1(void) |
{ |
init_mem(); |
unsigned int phaseno; |
for (phaseno = 0; phaseno < sizeof_array(phases); phaseno++) { |
phase_s *phase = &phases[phaseno]; |
TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name); |
do_phase(phase); |
if (error_flag) |
break; |
TPRINTF("Phase finished.\n"); |
} |
if (error_flag) |
return "Test failed"; |
return NULL; |
} |
/branches/network/uspace/app/tester/fault/fault1.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault1(bool quiet) |
char *test_fault1(void) |
{ |
((int *)(0))[1] = 0; |
/branches/network/uspace/app/tester/fault/fault2.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault2(bool quiet) |
char *test_fault2(void) |
{ |
volatile long long var; |
volatile int var1; |
/branches/network/uspace/app/tester/ipc/send_sync.def |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/answer.def |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/send_async.def |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/answer.c |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/hangup.def |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/send_async.c |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/send_sync.c |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/hangup.c |
---|
File deleted |
/branches/network/uspace/app/tester/ipc/ping_pong.c |
---|
37,20 → 37,23 |
#define DURATION_SECS 10 |
#define COUNT_GRANULARITY 100 |
char *test_ping_pong(bool quiet) |
char *test_ping_pong(void) |
{ |
printf("Pinging ns server for %d seconds...\n", DURATION_SECS); |
TPRINTF("Pinging ns server for %d seconds...", DURATION_SECS); |
struct timeval start; |
if (gettimeofday(&start, NULL) != 0) |
return "Failed getting the time."; |
if (gettimeofday(&start, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
uint64_t count = 0; |
while (true) { |
struct timeval now; |
if (gettimeofday(&now, NULL) != 0) |
return "Failed getting the time."; |
if (gettimeofday(&now, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) |
break; |
59,14 → 62,16 |
for (i = 0; i < COUNT_GRANULARITY; i++) { |
int retval = async_req_0_0(PHONE_NS, NS_PING); |
if (retval != EOK) |
return "Failed to send ping message."; |
if (retval != EOK) { |
TPRINTF("\n"); |
return "Failed to send ping message"; |
} |
} |
count += COUNT_GRANULARITY; |
} |
printf("Completed %lu round trips in %u seconds, %lu RT/s.\n", |
TPRINTF("OK\nCompleted %llu round trips in %u seconds, %llu rt/s.\n", |
count, DURATION_SECS, count / DURATION_SECS); |
return NULL; |
/branches/network/uspace/app/tester/ipc/register.c |
---|
32,58 → 32,58 |
#include <errno.h> |
#include "../tester.h" |
#define MAX_CONNECTIONS 50 |
static int connections[MAX_CONNECTIONS]; |
static void client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phonehash = icall->in_phone_hash; |
int retval; |
int i; |
unsigned int i; |
printf("Connected phone: %P, accepting\n", icall->in_phone_hash); |
TPRINTF("Connected phone %#x accepting\n", icall->in_phone_hash); |
ipc_answer_0(iid, EOK); |
for (i = 0; i < 1024; i++) |
for (i = 0; i < MAX_CONNECTIONS; i++) { |
if (!connections[i]) { |
connections[i] = phonehash; |
connections[i] = icall->in_phone_hash; |
break; |
} |
} |
while (1) { |
callid = async_get_call(&call); |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
int retval; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("Phone (%P) hung up.\n", phonehash); |
TPRINTF("Phone %#x hung up\n", icall->in_phone_hash); |
retval = 0; |
break; |
case IPC_TEST_METHOD: |
TPRINTF("Received well known message from %#x: %#x\n", |
icall->in_phone_hash, callid); |
ipc_answer_0(callid, EOK); |
break; |
default: |
printf("Received message from %P: %X\n", phonehash, |
callid); |
for (i = 0; i < 1024; i++) |
if (!callids[i]) { |
callids[i] = callid; |
TPRINTF("Received unknown message from %#x: %#x\n", |
icall->in_phone_hash, callid); |
ipc_answer_0(callid, ENOENT); |
break; |
} |
continue; |
} |
ipc_answer_0(callid, retval); |
} |
} |
char * test_register(bool quiet) |
char *test_register(void) |
{ |
int i; |
async_set_client_connection(client_connection); |
for (i = IPC_TEST_START; i < IPC_TEST_START + 10; i++) { |
ipcarg_t phonead; |
int res = ipc_connect_to_me(PHONE_NS, i, 0, 0, &phonead); |
if (!res) |
break; |
printf("Failed registering as %d..:%d\n", i, res); |
} |
printf("Registered as service: %d\n", i); |
myservice = i; |
int res = ipc_connect_to_me(PHONE_NS, IPC_TEST_SERVICE, 0, 0, &phonead); |
if (res != 0) |
return "Failed registering IPC service"; |
TPRINTF("Registered as service %u, accepting connections\n", IPC_TEST_SERVICE); |
async_manager(); |
return NULL; |
} |
/branches/network/uspace/app/tester/ipc/connect.c |
---|
28,32 → 28,46 |
#include <stdio.h> |
#include <unistd.h> |
#include <atomic.h> |
#include "../tester.h" |
char * test_connect(bool quiet) |
static atomic_t finish; |
static void callback(void *priv, int retval, ipc_call_t *data) |
{ |
char c; |
int svc; |
int phid; |
atomic_set(&finish, 1); |
} |
printf("Choose one service: 0:10000....9:10009 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '0' || c > '9'); |
char *test_connect(void) |
{ |
TPRINTF("Connecting to %u...", IPC_TEST_SERVICE); |
int phone = ipc_connect_me_to(PHONE_NS, IPC_TEST_SERVICE, 0, 0); |
if (phone > 0) { |
TPRINTF("phoneid %d\n", phone); |
} else { |
TPRINTF("\n"); |
return "ipc_connect_me_to() failed"; |
} |
svc = IPC_TEST_START + c - '0'; |
if (svc == myservice) |
return "Currently cannot connect to myself, update test"; |
printf("Sending synchronous message...\n"); |
int retval = ipc_call_sync_0_0(phone, IPC_TEST_METHOD); |
TPRINTF("Received response to synchronous message\n"); |
printf("Connecting to %d..", svc); |
phid = ipc_connect_me_to(PHONE_NS, svc, 0, 0); |
if (phid > 0) { |
printf("phoneid: %d\n", phid); |
phones[phid] = 1; |
} else |
return "Error"; |
TPRINTF("Sending asynchronous message...\n"); |
atomic_set(&finish, 0); |
ipc_call_async_0(phone, IPC_TEST_METHOD, NULL, callback, 1); |
while (atomic_get(&finish) != 1) |
TPRINTF("."); |
TPRINTF("Received response to asynchronous message\n"); |
TPRINTF("Hanging up..."); |
retval = ipc_hangup(phone); |
if (retval == 0) { |
TPRINTF("OK\n"); |
} else { |
TPRINTF("\n"); |
return "ipc_hangup() failed"; |
} |
return NULL; |
} |
/branches/network/uspace/app/tester/print/print2.c |
---|
0,0 → 1,52 |
/* |
* Copyright (c) 2005 Josef Cejka |
* 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. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
char *test_print2(void) |
{ |
TPRINTF("Testing printf(\"%%c %%3.2c %%-3.2c %%2.3c %%-2.3c\", 'a', 'b', 'c', 'd', 'e'):\n"); |
TPRINTF("Expected output: [a] [ b] [c ] [ d] [e ]\n"); |
TPRINTF("Real output: [%c] [%3.2c] [%-3.2c] [%2.3c] [%-2.3c]\n\n", 'a', 'b', 'c', 'd', 'e'); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", 1, 2, 3, 4, 5):\n"); |
TPRINTF("Expected output: [1] [ 02] [03 ] [004] [005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", 1, 2, 3, 4, 5); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", -1, -2, -3, -4, -5):\n"); |
TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); |
TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); |
TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); |
TPRINTF("Real output: [%#x] [%#5.3x] [%#-5.3x] [%#3.5x] [%#-3.5x]\n\n", 17, 18, 19, 20, 21); |
return NULL; |
} |
/branches/network/uspace/app/tester/print/print3.c |
---|
0,0 → 1,62 |
/* |
* Copyright (c) 2005 Josef Cejka |
* 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. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <macros.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char *test_print3(void) |
{ |
char buffer[BUFFER_SIZE]; |
int retval; |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=30 buffer=\"Short text without parameters.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very very very long text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=44 buffer=\"Very very very long text withou\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short %%s.\", \"text\"):\n"); |
TPRINTF("Expected result: retval=11 buffer=\"Short text.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s.", "text"); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very long %%s. This text's length is more than %%d. We are interested in the result.\", \"text\", " STRING(BUFFER_SIZE) "):\n"); |
TPRINTF("Expected result: retval=84 buffer=\"Very long text. This text's len\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text's length is more than %d. We are interested in the result.", "text", BUFFER_SIZE); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
return NULL; |
} |
/branches/network/uspace/app/tester/print/print4.c |
---|
30,63 → 30,54 |
#include <unistd.h> |
#include "../tester.h" |
#define PRIx8 "x" |
char *test_print4(bool quiet) |
char *test_print4(void) |
{ |
if (!quiet) { |
printf("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
TPRINTF("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
uint8_t group; |
for (group = 1; group < 4; group++) { |
printf("%#" PRIx8 ": ", group << 5); |
TPRINTF("%#x: ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
printf("%c", (char) ((group << 5) + index)); |
TPRINTF("%c", (char) ((group << 5) + index)); |
printf(" "); |
TPRINTF(" "); |
for (index = 0; index < 32; index++) |
printf("%lc", (wchar_t) ((group << 5) + index)); |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
printf("\n"); |
TPRINTF("\n"); |
} |
printf("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
for (group = 4; group < 8; group++) { |
printf("%#" PRIx8 ": ", group << 5); |
TPRINTF("%#x: ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
printf("%lc", (wchar_t) ((group << 5) + index)); |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
printf("\n"); |
TPRINTF("\n"); |
} |
printf("\nUTF-8 strings using printf(\"%%s\"):\n"); |
printf("English: %s\n", "Quick brown fox jumps over the lazy dog"); |
printf("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy"); |
printf("Greek: %s\n", "Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
printf("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה"); |
printf("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي"); |
printf("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой"); |
printf("Armenian: %s\n", "Սկսեց հրատարակվել Երուսաղեմի հայկական"); |
TPRINTF("\nUTF-8 strings using printf(\"%%s\"):\n"); |
TPRINTF("English: %s\n", "Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %s\n", "Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %s\n", "Սկսեց հրատարակվել Երուսաղեմի հայկական"); |
printf("\nUTF-32 strings using printf(\"%%ls\"):\n"); |
printf("English: %ls\n", L"Quick brown fox jumps over the lazy dog"); |
printf("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy"); |
printf("Greek: %ls\n", L"Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
printf("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה"); |
printf("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي"); |
printf("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой"); |
printf("Armenian: %ls\n", L"Սկսեց հրատարակվել Երուսաղեմի հայկական"); |
TPRINTF("\nUTF-32 strings using printf(\"%%ls\"):\n"); |
TPRINTF("English: %ls\n", L"Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %ls\n", L"Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %ls\n", L"Սկսեց հրատարակվել Երուսաղեմի հայկական"); |
printf("Test: [%d] '%lc'\n", L'\x0161', L'\x0161'); |
} |
printf("[Press a key]\n"); |
getchar(); |
return NULL; |
} |
/branches/network/uspace/app/tester/print/print1.def |
---|
1,6 → 1,6 |
{ |
"print1", |
"Printf test", |
"String printf test", |
&test_print1, |
true |
}, |
/branches/network/uspace/app/tester/print/print2.def |
---|
0,0 → 1,6 |
{ |
"print2", |
"Numeric printf test", |
&test_print2, |
true |
}, |
/branches/network/uspace/app/tester/print/print3.def |
---|
0,0 → 1,6 |
{ |
"print3", |
"Buffered printf test", |
&test_print3, |
true |
}, |
/branches/network/uspace/app/tester/print/print1.c |
---|
30,44 → 30,27 |
#include <unistd.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char * test_print1(bool quiet) |
char *test_print1(void) |
{ |
if (!quiet) { |
int retval; |
unsigned int nat = 0x12345678u; |
TPRINTF("Testing printf(\"%%*.*s\", 5, 3, \"text\"):\n"); |
TPRINTF("Expected output: \" tex\"\n"); |
TPRINTF("Real output: \"%*.*s\"\n\n", 5, 3, "text"); |
char buffer[BUFFER_SIZE]; |
TPRINTF("Testing printf(\"%%10.8s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \" very lon\"\n"); |
TPRINTF("Real output: \"%10.8s\"\n\n", "very long text"); |
printf(" text 10.8s %*.*s \n", 5, 3, "text"); |
printf(" very long text 10.8s %10.8s \n", "very long text"); |
printf(" text 8.10s %8.10s \n", "text"); |
printf(" very long text 8.10s %8.10s \n", "very long text"); |
TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n"); |
TPRINTF("Expected output: \"text\"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "text"); |
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n",'a', 'b', 'c', 'd', 'e' ); |
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",1, 1, 1, 1, 1 ); |
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 ); |
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 ); |
TPRINTF("Testing printf(\"%%8.10s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \"very long \"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "very long text"); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
TPRINTF("Testing printf(\"%%s\", NULL):\n"); |
TPRINTF("Expected output: \"(NULL)\"\n"); |
TPRINTF("Real output: \"%s\"\n\n", NULL); |
printf(" Print to NULL '%s'\n", NULL); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print short text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s", "text"); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print long text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text`s length is more than %d. We are interested in the result.", "text" , BUFFER_SIZE); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
} |
return NULL; |
} |
/branches/network/uspace/app/tester/tester.h |
---|
39,18 → 39,22 |
#include <bool.h> |
#include <ipc/ipc.h> |
#define IPC_TEST_START 10000 |
#define MAX_PHONES 20 |
#define MAX_CONNECTIONS 50 |
#define TEST_SKIPPED "Test Skipped" |
#define IPC_TEST_SERVICE 10240 |
#define IPC_TEST_METHOD 2000 |
extern int myservice; |
extern int phones[MAX_PHONES]; |
extern int connections[MAX_CONNECTIONS]; |
extern ipc_callid_t callids[MAX_CONNECTIONS]; |
extern bool test_quiet; |
extern int test_argc; |
extern char **test_argv; |
typedef char * (* test_entry_t)(bool); |
#define TPRINTF(format, ...) \ |
{ \ |
if (!test_quiet) { \ |
fprintf(stderr, format, ##__VA_ARGS__); \ |
} \ |
} |
typedef char *(*test_entry_t)(void); |
typedef struct { |
char * name; |
char * desc; |
58,24 → 62,22 |
bool safe; |
} test_t; |
extern char * test_thread1(bool quiet); |
extern char * test_print1(bool quiet); |
extern char * test_print4(bool quiet); |
extern char * test_fault1(bool quiet); |
extern char * test_fault2(bool quiet); |
extern char * test_register(bool quiet); |
extern char * test_connect(bool quiet); |
extern char * test_send_async(bool quiet); |
extern char * test_send_sync(bool quiet); |
extern char * test_answer(bool quiet); |
extern char * test_hangup(bool quiet); |
extern char * test_ping_pong(bool quiet); |
extern char * test_devmap1(bool quiet); |
extern char * test_loop1(bool quiet); |
extern char * test_vfs1(bool quiet); |
extern char * test_console1(bool quiet); |
extern char * test_stdio1(bool quiet); |
extern char * test_stdio2(bool quiet); |
extern char *test_thread1(void); |
extern char *test_print1(void); |
extern char *test_print2(void); |
extern char *test_print3(void); |
extern char *test_print4(void); |
extern char *test_console1(void); |
extern char *test_stdio1(void); |
extern char *test_stdio2(void); |
extern char *test_fault1(void); |
extern char *test_fault2(void); |
extern char *test_vfs1(void); |
extern char *test_ping_pong(void); |
extern char *test_register(void); |
extern char *test_connect(void); |
extern char *test_loop1(void); |
extern char *test_malloc1(void); |
extern test_t tests[]; |
/branches/network/uspace/app/tester/Makefile |
---|
45,22 → 45,20 |
SOURCES = tester.c \ |
thread/thread1.c \ |
print/print1.c \ |
print/print2.c \ |
print/print3.c \ |
print/print4.c \ |
console/console1.c \ |
stdio/stdio1.c \ |
stdio/stdio2.c \ |
fault/fault1.c \ |
fault/fault2.c \ |
vfs/vfs1.c \ |
ipc/ping_pong.c \ |
ipc/register.c \ |
ipc/connect.c \ |
ipc/send_async.c \ |
ipc/send_sync.c \ |
ipc/answer.c \ |
ipc/hangup.c \ |
ipc/ping_pong.c \ |
loop/loop1.c \ |
devmap/devmap1.c \ |
console/console1.c \ |
stdio/stdio1.c \ |
stdio/stdio2.c \ |
vfs/vfs1.c |
mm/malloc1.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
/branches/network/uspace/app/tester/vfs/vfs1.c |
---|
34,109 → 34,118 |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include "../tester.h" |
char text[] = "O xein', angellein Lakedaimoniois hoti teide " |
"keimetha tois keinon rhemasi peithomenoi."; |
#define FS_TYPE "tmpfs" |
#define MOUNT_POINT "/tmp" |
#define OPTIONS "" |
#define FLAGS 0 |
char *test_vfs1(bool quiet) |
#define TEST_DIRECTORY MOUNT_POINT "/testdir" |
#define TEST_FILE TEST_DIRECTORY "/testfile" |
#define TEST_FILE2 TEST_DIRECTORY "/nextfile" |
#define MAX_DEVICE_NAME 32 |
#define BUF_SIZE 16 |
static char text[] = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; |
static char *read_root(void) |
{ |
int rc; |
TPRINTF("Opening the root directory..."); |
rc = mount("tmpfs", "/", "nulldev0", "", 0); |
DIR *dirp = opendir("/"); |
if (!dirp) { |
TPRINTF("\n"); |
return "opendir() failed"; |
} else |
TPRINTF("OK\n"); |
struct dirent *dp; |
while ((dp = readdir(dirp))) |
TPRINTF(" node \"%s\"\n", dp->d_name); |
closedir(dirp); |
return NULL; |
} |
char *test_vfs1(void) |
{ |
if (mkdir(MOUNT_POINT, 0) != 0) |
return "mkdir() failed"; |
TPRINTF("Created directory %s\n", MOUNT_POINT); |
char null[MAX_DEVICE_NAME]; |
int null_id = devmap_null_create(); |
if (null_id == -1) |
return "Unable to create null device"; |
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id); |
int rc = mount(FS_TYPE, MOUNT_POINT, null, OPTIONS, FLAGS); |
switch (rc) { |
case EOK: |
if (!quiet) |
printf("mounted tmpfs on /\n"); |
TPRINTF("Mounted /dev/%s as %s on %s\n", null, FS_TYPE, MOUNT_POINT); |
break; |
case EBUSY: |
if (!quiet) |
printf("(INFO) something is already mounted on /\n"); |
TPRINTF("(INFO) Filesystem already mounted on %s\n", MOUNT_POINT); |
break; |
default: |
if (!quiet) |
printf("(INFO) IPC returned errno %d\n", rc); |
return "mount() failed."; |
TPRINTF("(ERR) IPC returned errno %d (is tmpfs loaded?)\n", rc); |
return "mount() failed"; |
} |
if (mkdir("/mydir", 0) != 0) |
return "mkdir() failed.\n"; |
if (!quiet) |
printf("created directory /mydir\n"); |
if (mkdir(TEST_DIRECTORY, 0) != 0) |
return "mkdir() failed"; |
TPRINTF("Created directory %s\n", TEST_DIRECTORY); |
int fd0 = open("/mydir/myfile", O_CREAT); |
int fd0 = open(TEST_FILE, O_CREAT); |
if (fd0 < 0) |
return "open() failed.\n"; |
if (!quiet) |
printf("created file /mydir/myfile, fd=%d\n", fd0); |
return "open() failed"; |
TPRINTF("Created file %s (fd=%d)\n", TEST_FILE, fd0); |
ssize_t cnt; |
size_t size = sizeof(text); |
cnt = write(fd0, text, size); |
ssize_t cnt = write(fd0, text, size); |
if (cnt < 0) |
return "write() failed.\n"; |
if (!quiet) |
printf("written %d bytes, fd=%d\n", cnt, fd0); |
return "write() failed"; |
TPRINTF("Written %d bytes\n", cnt); |
if (lseek(fd0, 0, SEEK_SET) != 0) |
return "lseek() failed.\n"; |
if (!quiet) |
printf("sought to position 0, fd=%d\n", fd0); |
return "lseek() failed"; |
TPRINTF("Sought to position 0\n"); |
char buf[10]; |
char buf[BUF_SIZE]; |
while ((cnt = read(fd0, buf, BUF_SIZE))) { |
if (cnt < 0) |
return "read() failed"; |
while ((cnt = read(fd0, buf, sizeof(buf)))) { |
if (cnt < 0) |
return "read() failed.\n"; |
if (!quiet) |
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt, |
buf, fd0); |
TPRINTF("Read %d bytes: \".*s\"\n", cnt, cnt, buf); |
} |
close(fd0); |
DIR *dirp; |
struct dirent *dp; |
char *rv = read_root(); |
if (rv != NULL) |
return rv; |
if (!quiet) |
printf("scanning the root directory...\n"); |
if (rename(TEST_FILE, TEST_FILE2)) |
return "rename() failed"; |
TPRINTF("Renamed %s to %s\n", TEST_FILE, TEST_FILE2); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
if (unlink(TEST_FILE2)) |
return "unlink() failed"; |
TPRINTF("Unlinked %s\n", TEST_FILE2); |
if (rename("/mydir/myfile", "/mydir/yourfile")) |
return "rename() failed.\n"; |
if (rmdir(TEST_DIRECTORY)) |
return "rmdir() failed"; |
TPRINTF("Removed directory %s\n", TEST_DIRECTORY); |
if (!quiet) |
printf("renamed /mydir/myfile to /mydir/yourfile\n"); |
rv = read_root(); |
if (rv != NULL) |
return rv; |
if (unlink("/mydir/yourfile")) |
return "unlink() failed.\n"; |
if (!quiet) |
printf("unlinked file /mydir/yourfile\n"); |
if (rmdir("/mydir")) |
return "rmdir() failed.\n"; |
if (!quiet) |
printf("removed directory /mydir\n"); |
if (!quiet) |
printf("scanning the root directory...\n"); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
return NULL; |
} |
/branches/network/uspace/app/getvc/getvc.c |
---|
73,6 → 73,9 |
int main(int argc, char *argv[]) |
{ |
task_exit_t texit; |
int retval; |
if (argc < 3) { |
usage(); |
return -1; |
97,7 → 100,7 |
version_print(argv[1]); |
task_id_t id = spawn(argv[2]); |
task_wait(id); |
task_wait(id, &texit, &retval); |
return 0; |
} |
/branches/network/uspace/app/tetris/screen.c |
---|
62,6 → 62,8 |
static int curscore; |
static int isset; /* true => terminal is in game mode */ |
static int use_color; /* true => use colors */ |
static const struct shape *lastshape; |
78,7 → 80,8 |
static void start_standout(uint32_t color) |
{ |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, color); |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, |
use_color ? color : 0x000000); |
} |
static void resume_normal(void) |
127,6 → 130,18 |
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row); |
} |
static int get_display_color_sup(void) |
{ |
int rc; |
int ccap; |
rc = console_get_color_cap(fphone(stdout), &ccap); |
if (rc != 0) |
return 0; |
return (ccap >= CONSOLE_CCAP_RGB); |
} |
/* |
* Set up screen mode. |
*/ |
142,6 → 157,8 |
Cols = ws.ws_col; |
} |
use_color = get_display_color_sup(); |
if ((Rows < MINROWS) || (Cols < MINCOLS)) { |
char smallscr[55]; |
/branches/network/uspace/app/tetris/shapes.c |
---|
87,7 → 87,7 |
*/ |
int fits_in(const struct shape *shape, int pos) |
{ |
int *o = shape->off; |
const int *o = shape->off; |
if ((board[pos]) || (board[pos + *o++]) || (board[pos + *o++]) || |
(board[pos + *o])) |
102,7 → 102,7 |
*/ |
void place(const struct shape *shape, int pos, int onoff) |
{ |
int *o = shape->off; |
const int *o = shape->off; |
board[pos] = onoff ? shape->color : 0x000000; |
board[pos + *o++] = onoff ? shape->color : 0x000000; |
/branches/network/uspace/app/tetris/tetris.c |
---|
237,7 → 237,7 |
{ |
int pos; |
int c; |
char *keys; |
const char *keys; |
int level = 2; |
char key_write[6][10]; |
int i; |
/branches/network/uspace/app/trace/trace.c |
---|
43,7 → 43,11 |
#include <task.h> |
#include <mem.h> |
#include <string.h> |
#include <bool.h> |
#include <loader/loader.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <fibril_sync.h> |
#include <libc.h> |
64,22 → 68,31 |
int next_thread_id; |
ipc_call_t thread_ipc_req[THBUF_SIZE]; |
int phoneid; |
int abort_trace; |
bool abort_trace; |
uintptr_t thash; |
volatile int paused; |
static bool paused; |
static fibril_condvar_t state_cv; |
static fibril_mutex_t state_lock; |
static bool cev_valid; |
static console_event_t cev; |
void thread_trace_start(uintptr_t thread_hash); |
static proto_t *proto_console; |
static task_id_t task_id; |
static loader_t *task_ldr; |
static bool task_wait_for; |
/** Combination of events/data to print. */ |
display_mask_t display_mask; |
static int program_run_fibril(void *arg); |
static int cev_fibril(void *arg); |
static void program_run(void) |
{ |
94,6 → 107,19 |
fibril_add_ready(fid); |
} |
static void cev_fibril_start(void) |
{ |
fid_t fid; |
fid = fibril_create(cev_fibril, NULL); |
if (fid == 0) { |
printf("Error creating fibril\n"); |
exit(1); |
} |
fibril_add_ready(fid); |
} |
static int program_run_fibril(void *arg) |
{ |
int rc; |
180,6 → 206,10 |
void val_print(sysarg_t val, val_type_t v_type) |
{ |
long sval; |
sval = (long) val; |
switch (v_type) { |
case V_VOID: |
printf("<void>"); |
186,7 → 216,7 |
break; |
case V_INTEGER: |
printf("%ld", val); |
printf("%ld", sval); |
break; |
case V_HASH: |
195,29 → 225,29 |
break; |
case V_ERRNO: |
if (val >= -15 && val <= 0) { |
printf("%ld %s (%s)", val, |
err_desc[-val].name, |
err_desc[-val].desc); |
if (sval >= -15 && sval <= 0) { |
printf("%ld %s (%s)", sval, |
err_desc[-sval].name, |
err_desc[-sval].desc); |
} else { |
printf("%ld", val); |
printf("%ld", sval); |
} |
break; |
case V_INT_ERRNO: |
if (val >= -15 && val < 0) { |
printf("%ld %s (%s)", val, |
err_desc[-val].name, |
err_desc[-val].desc); |
if (sval >= -15 && sval < 0) { |
printf("%ld %s (%s)", sval, |
err_desc[-sval].name, |
err_desc[-sval].desc); |
} else { |
printf("%ld", val); |
printf("%ld", sval); |
} |
break; |
case V_CHAR: |
if (val >= 0x20 && val < 0x7f) { |
printf("'%c'", val); |
if (sval >= 0x20 && sval < 0x7f) { |
printf("'%c'", sval); |
} else { |
switch (val) { |
switch (sval) { |
case '\a': printf("'\\a'"); break; |
case '\b': printf("'\\b'"); break; |
case '\n': printf("'\\n'"); break; |
256,7 → 286,8 |
ipc_call_t call; |
ipcarg_t phoneid; |
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY) |
if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL || |
sc_rc == (sysarg_t) IPC_CALLRET_TEMPORARY) |
return; |
phoneid = sc_args[0]; |
276,7 → 307,8 |
ipc_call_t call; |
int rc; |
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY) |
if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL || |
sc_rc == (sysarg_t) IPC_CALLRET_TEMPORARY) |
return; |
memset(&call, 0, sizeof(call)); |
315,24 → 347,40 |
ipcp_call_sync(phoneidx, &question, &reply); |
} |
static void sc_ipc_call_sync_slow(sysarg_t *sc_args) |
static void sc_ipc_call_sync_slow_b(unsigned thread_id, sysarg_t *sc_args) |
{ |
ipc_call_t question, reply; |
ipc_call_t question; |
int rc; |
memset(&question, 0, sizeof(question)); |
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args)); |
printf("dmr->%d\n", rc); |
if (rc < 0) return; |
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], |
sizeof(question.args)); |
if (rc < 0) { |
printf("Error: mem_read->%d\n", rc); |
return; |
} |
thread_ipc_req[thread_id] = question; |
} |
static void sc_ipc_call_sync_slow_e(unsigned thread_id, sysarg_t *sc_args) |
{ |
ipc_call_t reply; |
int rc; |
memset(&reply, 0, sizeof(reply)); |
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args)); |
printf("dmr->%d\n", rc); |
if (rc < 0) return; |
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], |
sizeof(reply.args)); |
ipcp_call_sync(sc_args[0], &question, &reply); |
if (rc < 0) { |
printf("Error: mem_read->%d\n", rc); |
return; |
} |
ipcp_call_sync(sc_args[0], &thread_ipc_req[thread_id], &reply); |
} |
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc) |
{ |
ipc_call_t call; |
375,6 → 423,14 |
print_sc_args(sc_args, syscall_desc[sc_id].n_args); |
} |
switch (sc_id) { |
case SYS_IPC_CALL_SYNC_SLOW: |
sc_ipc_call_sync_slow_b(thread_id, sc_args); |
break; |
default: |
break; |
} |
async_serialize_end(); |
} |
415,7 → 471,7 |
sc_ipc_call_sync_fast(sc_args); |
break; |
case SYS_IPC_CALL_SYNC_SLOW: |
sc_ipc_call_sync_slow(sc_args); |
sc_ipc_call_sync_slow_e(thread_id, sc_args); |
break; |
case SYS_IPC_WAIT: |
sc_ipc_wait(sc_args, sc_rc); |
446,20 → 502,26 |
thread_hash = (uintptr_t)thread_hash_arg; |
thread_id = next_thread_id++; |
if (thread_id >= THBUF_SIZE) { |
printf("Too many threads.\n"); |
return ELIMIT; |
} |
printf("Start tracing thread [%d] (hash 0x%lx).\n", thread_id, thread_hash); |
while (!abort_trace) { |
fibril_mutex_lock(&state_lock); |
if (paused) { |
printf("Press R to resume (and be patient).\n"); |
while (paused) { |
usleep(1000000); |
fibril_yield(); |
printf("."); |
printf("Thread [%d] paused. Press R to resume.\n", |
thread_id); |
while (paused) |
fibril_condvar_wait(&state_cv, &state_lock); |
printf("Thread [%d] resumed.\n", thread_id); |
} |
printf("Resumed\n"); |
} |
fibril_mutex_unlock(&state_lock); |
/* Run thread until an event occurs */ |
rc = udebug_go(phoneid, thread_hash, |
481,6 → 543,9 |
break; |
case UDEBUG_EVENT_STOP: |
printf("Stop event\n"); |
fibril_mutex_lock(&state_lock); |
paused = true; |
fibril_mutex_unlock(&state_lock); |
break; |
case UDEBUG_EVENT_THREAD_B: |
event_thread_b(val0); |
487,7 → 552,10 |
break; |
case UDEBUG_EVENT_THREAD_E: |
printf("Thread 0x%lx exited.\n", val0); |
abort_trace = 1; |
fibril_mutex_lock(&state_lock); |
abort_trace = true; |
fibril_condvar_broadcast(&state_cv); |
fibril_mutex_unlock(&state_lock); |
break; |
default: |
printf("Unknown event type %d.\n", ev_type); |
540,6 → 608,33 |
if (rc != EOK) |
goto error; |
/* Send default files */ |
fdi_node_t *files[4]; |
fdi_node_t stdin_node; |
fdi_node_t stdout_node; |
fdi_node_t stderr_node; |
if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK)) |
files[0] = &stdin_node; |
else |
files[0] = NULL; |
if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK)) |
files[1] = &stdout_node; |
else |
files[1] = NULL; |
if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK)) |
files[2] = &stderr_node; |
else |
files[2] = NULL; |
files[3] = NULL; |
rc = loader_set_files(ldr, files); |
if (rc != EOK) |
goto error; |
/* Load the program. */ |
rc = loader_load_program(ldr); |
if (rc != EOK) |
555,11 → 650,32 |
return NULL; |
} |
static int cev_fibril(void *arg) |
{ |
(void) arg; |
while (true) { |
fibril_mutex_lock(&state_lock); |
while (cev_valid) |
fibril_condvar_wait(&state_cv, &state_lock); |
fibril_mutex_unlock(&state_lock); |
if (!console_get_event(fphone(stdin), &cev)) |
return -1; |
fibril_mutex_lock(&state_lock); |
cev_valid = true; |
fibril_condvar_broadcast(&state_cv); |
fibril_mutex_unlock(&state_lock); |
} |
} |
static void trace_task(task_id_t task_id) |
{ |
console_event_t ev; |
bool done; |
int i; |
int rc; |
int c; |
ipcp_init(); |
575,29 → 691,55 |
return; |
} |
abort_trace = 0; |
abort_trace = false; |
for (i = 0; i < n_threads; i++) { |
thread_trace_start(thread_hash_buf[i]); |
} |
while(1) { |
c = getchar(); |
if (c == 'q') break; |
if (c == 'p') { |
done = false; |
while (!done) { |
fibril_mutex_lock(&state_lock); |
while (!cev_valid && !abort_trace) |
fibril_condvar_wait(&state_cv, &state_lock); |
fibril_mutex_unlock(&state_lock); |
ev = cev; |
fibril_mutex_lock(&state_lock); |
cev_valid = false; |
fibril_condvar_broadcast(&state_cv); |
fibril_mutex_unlock(&state_lock); |
if (abort_trace) |
break; |
if (ev.type != KEY_PRESS) |
continue; |
switch (ev.key) { |
case KC_Q: |
done = true; |
break; |
case KC_P: |
printf("Pause...\n"); |
paused = 1; |
rc = udebug_stop(phoneid, thash); |
printf("stop -> %d\n", rc); |
} |
if (c == 'r') { |
paused = 0; |
if (rc != EOK) |
printf("Error: stop -> %d\n", rc); |
break; |
case KC_R: |
fibril_mutex_lock(&state_lock); |
paused = false; |
fibril_condvar_broadcast(&state_cv); |
fibril_mutex_unlock(&state_lock); |
printf("Resume...\n"); |
break; |
} |
} |
printf("\nTerminate debugging session...\n"); |
abort_trace = 1; |
abort_trace = true; |
udebug_end(phoneid); |
ipc_hangup(phoneid); |
629,37 → 771,53 |
}; |
next_thread_id = 1; |
paused = 0; |
paused = false; |
cev_valid = false; |
fibril_mutex_initialize(&state_lock); |
fibril_condvar_initialize(&state_cv); |
proto_init(); |
p = proto_new("vfs"); |
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_OPEN, o); |
o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_OPEN_NODE, o); |
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_READ, o); |
proto_add_oper(p, VFS_IN_READ, o); |
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_WRITE, o); |
proto_add_oper(p, VFS_IN_WRITE, o); |
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_SEEK, o); |
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_TRUNCATE, o); |
proto_add_oper(p, VFS_IN_TRUNCATE, o); |
o = oper_new("fstat", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_FSTAT, o); |
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_CLOSE, o); |
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MOUNT, o); |
proto_add_oper(p, VFS_IN_MOUNT, o); |
/* o = oper_new("unmount", 0, arg_def); |
proto_add_oper(p, VFS_UNMOUNT, o);*/ |
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_OPEN, o); |
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_CLOSE, o); |
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_SEEK, o); |
proto_add_oper(p, VFS_IN_UNMOUNT, o);*/ |
o = oper_new("sync", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_SYNC, o); |
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MKDIR, o); |
proto_add_oper(p, VFS_IN_MKDIR, o); |
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_UNLINK, o); |
proto_add_oper(p, VFS_IN_UNLINK, o); |
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_RENAME, o); |
proto_add_oper(p, VFS_IN_RENAME, o); |
o = oper_new("stat", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_STAT, o); |
proto_register(SERVICE_VFS, p); |
p = proto_new("console"); |
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_IN_WRITE, o); |
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER; |
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR; |
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def); |
752,6 → 910,7 |
--argc; ++argv; |
task_id = strtol(*argv, &err_p, 10); |
task_ldr = NULL; |
task_wait_for = false; |
if (*err_p) { |
printf("Task ID syntax error\n"); |
print_syntax(); |
789,6 → 948,7 |
while (*cp) printf("'%s'\n", *cp++); |
} |
task_ldr = preload_task(*argv, argv, &task_id); |
task_wait_for = true; |
return 0; |
} |
796,6 → 956,8 |
int main(int argc, char *argv[]) |
{ |
int rc; |
task_exit_t texit; |
int retval; |
printf("System Call / IPC Tracer\n"); |
printf("Controls: Q - Quit, P - Pause, R - Resume\n"); |
815,12 → 977,29 |
printf("Connected to task %lld.\n", task_id); |
if (task_ldr != NULL) { |
if (task_ldr != NULL) |
program_run(); |
} |
cev_fibril_start(); |
trace_task(task_id); |
if (task_wait_for) { |
printf("Waiting for task to exit.\n"); |
rc = task_wait(task_id, &texit, &retval); |
if (rc != EOK) { |
printf("Failed waiting for task.\n"); |
return -1; |
} |
if (texit == TASK_EXIT_NORMAL) { |
printf("Task exited normally, return value %d.\n", |
retval); |
} else { |
printf("Task exited unexpectedly.\n"); |
} |
} |
return 0; |
} |
/branches/network/uspace/app/trace/proto.c |
---|
46,7 → 46,7 |
hash_table_t srv_proto; |
typedef struct { |
int srv; |
unsigned srv; |
proto_t *proto; |
link_t link; |
} srv_proto_t; |
/branches/network/uspace/lib/libfs/libfs.c |
---|
43,6 → 43,7 |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
#include <sys/stat.h> |
/** Register file system server. |
* |
69,7 → 70,7 |
* out-of-order, when it knows that the operation succeeded or failed. |
*/ |
ipc_call_t answer; |
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer); |
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); |
/* |
* Send our VFS info structure to VFS. |
104,7 → 105,7 |
} |
/* |
* Pick up the answer for the request to the VFS_REQUEST call. |
* Pick up the answer for the request to the VFS_IN_REQUEST call. |
*/ |
async_wait_for(req, NULL); |
reg->fs_handle = (int) IPC_GET_ARG1(answer); |
186,7 → 187,7 |
} |
ipc_call_t answer; |
aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle, |
aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle, |
&answer); |
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
213,8 → 214,8 |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
* @param rid Request ID of the VFS_OUT_LOOKUP request. |
* @param request VFS_OUT_LOOKUP request data itself. |
* |
*/ |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
237,7 → 238,7 |
fs_node_t *tmp = NULL; |
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP, |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP, |
next, last, cur->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
272,9 → 273,9 |
else |
next--; |
ipc_forward_slow(rid, tmp->mp_data.phone, VFS_LOOKUP, |
next, last, tmp->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ipc_forward_slow(rid, tmp->mp_data.phone, |
VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, |
lflag, index, IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
ops->node_put(tmp); |
if (par) |
428,12 → 429,42 |
ops->node_put(tmp); |
} |
void libfs_stat(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_node_t *fn = ops->node_get(dev_handle, index); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size) || |
size != sizeof(struct stat)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
struct stat stat; |
memset(&stat, 0, sizeof(struct stat)); |
stat.fs_handle = fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = ops->lnkcnt_get(fn); |
stat.is_file = ops->is_file(fn); |
stat.size = ops->size_get(fn); |
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
/** Open VFS triplet. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param rid Request ID of the VFS_OPEN_NODE request. |
* @param request VFS_OPEN_NODE request data itself. |
* @param rid Request ID of the VFS_OUT_OPEN_NODE request. |
* @param request VFS_OUT_OPEN_NODE request data itself. |
* |
*/ |
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
/branches/network/uspace/lib/libfs/libfs.h |
---|
84,6 → 84,7 |
extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t, |
ipc_call_t *); |
/branches/network/uspace/lib/libblock/libblock.c |
---|
63,6 → 63,7 |
fibril_mutex_t lock; |
size_t block_size; /**< Block size. */ |
unsigned block_count; /**< Total number of blocks. */ |
unsigned blocks_cached; /**< Number of cached blocks. */ |
hash_table_t block_hash; |
link_t free_head; |
enum cache_mode mode; |
72,6 → 73,7 |
link_t link; |
dev_handle_t dev_handle; |
int dev_phone; |
fibril_mutex_t com_area_lock; |
void *com_area; |
size_t com_size; |
void *bb_buf; |
80,8 → 82,8 |
cache_t *cache; |
} devcon_t; |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size, |
const void *src); |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static devcon_t *devcon_search(dev_handle_t dev_handle) |
{ |
112,6 → 114,7 |
link_initialize(&devcon->link); |
devcon->dev_handle = dev_handle; |
devcon->dev_phone = dev_phone; |
fibril_mutex_initialize(&devcon->com_area_lock); |
devcon->com_area = com_area; |
devcon->com_size = com_size; |
devcon->bb_buf = NULL; |
211,14 → 214,16 |
if (!bb_buf) |
return ENOMEM; |
off_t bufpos = 0; |
size_t buflen = 0; |
rc = block_read(dev_handle, &bufpos, &buflen, &off, |
bb_buf, size, size); |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, 0, size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
free(bb_buf); |
return rc; |
} |
memcpy(bb_buf, devcon->com_area, size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
devcon->bb_buf = bb_buf; |
devcon->bb_off = off; |
devcon->bb_size = size; |
271,6 → 276,7 |
list_initialize(&cache->free_head); |
cache->block_size = size; |
cache->block_count = blocks; |
cache->blocks_cached = 0; |
cache->mode = mode; |
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, |
283,9 → 289,15 |
return EOK; |
} |
#define CACHE_LO_WATERMARK 10 |
#define CACHE_HI_WATERMARK 20 |
static bool cache_can_grow(cache_t *cache) |
{ |
if (cache->blocks_cached < CACHE_LO_WATERMARK) |
return true; |
if (!list_empty(&cache->free_head)) |
return false; |
return true; |
} |
static void block_initialize(block_t *b) |
315,6 → 327,7 |
block_t *b; |
link_t *l; |
unsigned long key = boff; |
bn_t oboff; |
devcon = devcon_search(dev_handle); |
339,9 → 352,6 |
* The block was not found in the cache. |
*/ |
int rc; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = boff * cache->block_size; |
bool sync = false; |
if (cache_can_grow(cache)) { |
358,6 → 368,7 |
free(b); |
goto recycle; |
} |
cache->blocks_cached++; |
} else { |
/* |
* Try to recycle a block from the free list. |
367,8 → 378,9 |
assert(!list_empty(&cache->free_head)); |
l = cache->free_head.next; |
list_remove(l); |
b = hash_table_get_instance(l, block_t, hash_link); |
b = list_get_instance(l, block_t, free_link); |
sync = b->dirty; |
oboff = b->boff; |
temp_key = b->boff; |
hash_table_remove(&cache->block_hash, &temp_key, 1); |
} |
392,7 → 404,11 |
* The block is dirty and needs to be written back to |
* the device before we can read in the new contents. |
*/ |
abort(); /* TODO: block_write() */ |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, b->data, b->size); |
rc = write_block(devcon, oboff, cache->block_size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
if (!(flags & BLOCK_FLAGS_NOREAD)) { |
/* |
399,9 → 415,11 |
* The block contains old or no data. We need to read |
* the new contents from the device. |
*/ |
rc = block_read(dev_handle, &bufpos, &buflen, &pos, |
b->data, cache->block_size, cache->block_size); |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, b->boff, cache->block_size); |
assert(rc == EOK); |
memcpy(b->data, devcon->com_area, cache->block_size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
fibril_mutex_unlock(&b->lock); |
429,14 → 447,43 |
fibril_mutex_lock(&block->lock); |
if (!--block->refcnt) { |
/* |
* Last reference to the block was dropped, put the block on the |
* free list. |
* Last reference to the block was dropped. Either free the |
* block or put it on the free list. |
*/ |
if (cache->blocks_cached > CACHE_HI_WATERMARK) { |
/* |
* Currently there are too many cached blocks. |
*/ |
if (block->dirty) { |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, |
block->size); |
rc = write_block(devcon, block->boff, |
block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
/* |
* Take the block out of the cache and free it. |
*/ |
unsigned long key = block->boff; |
hash_table_remove(&cache->block_hash, &key, 1); |
free(block); |
free(block->data); |
cache->blocks_cached--; |
fibril_mutex_unlock(&cache->lock); |
return; |
} |
/* |
* Put the block on the free list. |
*/ |
list_append(&block->free_link, &cache->free_head); |
if (cache->mode != CACHE_MODE_WB && block->dirty) { |
rc = write_block(devcon, block->boff, block->size, |
block->data); |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, block->size); |
rc = write_block(devcon, block->boff, block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
block->dirty = false; |
} |
445,7 → 492,7 |
fibril_mutex_unlock(&cache->lock); |
} |
/** Read data from a block device. |
/** Read sequential data from a block device. |
* |
* @param dev_handle Device handle of the block device. |
* @param bufpos Pointer to the first unread valid offset within the |
459,9 → 506,8 |
* |
* @return EOK on success or a negative return code on failure. |
*/ |
int |
block_read(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, |
void *dst, size_t size, size_t block_size) |
int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen, |
off_t *pos, void *dst, size_t size, size_t block_size) |
{ |
off_t offset = 0; |
size_t left = size; |
468,6 → 514,7 |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
fibril_mutex_lock(&devcon->com_area_lock); |
while (left > 0) { |
size_t rd; |
490,20 → 537,46 |
if (*bufpos == (off_t) *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
int rc; |
rc = read_block(devcon, *pos / block_size, block_size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
return rc; |
} |
*bufpos = 0; |
*buflen = block_size; |
} |
} |
fibril_mutex_unlock(&devcon->com_area_lock); |
return EOK; |
} |
/** Read block from block device. |
* |
* @param devcon Device connection. |
* @param boff Block index. |
* @param block_size Block size. |
* @param src Buffer for storing the data. |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
return EOK; |
} |
/** Write block to block device. |
* |
* @param devcon Device connection. |
513,17 → 586,14 |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size, |
const void *src) |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
memcpy(devcon->com_area, src, block_size); |
rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, |
boff, block_size, &retval); |
rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
/branches/network/uspace/lib/libblock/libblock.h |
---|
100,11 → 100,11 |
extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode); |
extern block_t *block_get(dev_handle_t, bn_t, int flags); |
extern block_t *block_get(dev_handle_t, bn_t, int); |
extern void block_put(block_t *); |
extern int block_read(dev_handle_t, off_t *, size_t *, off_t *, void *, size_t, |
size_t); |
extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/branches/network/uspace/lib/libc/malloc/malloc.c |
---|
File deleted |
/branches/network/uspace/lib/libc/include/getopt.h |
---|
58,7 → 58,7 |
}; |
/* HelenOS Port - These need to be exposed for legacy getopt() */ |
extern char *optarg; |
extern const char *optarg; |
extern int optind, opterr, optopt; |
extern int optreset; |
/branches/network/uspace/lib/libc/include/string.h |
---|
74,8 → 74,8 |
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); |
extern const char *str_chr(const char *str, wchar_t ch); |
extern const char *str_rchr(const char *str, wchar_t ch); |
extern char *str_chr(const char *str, wchar_t ch); |
extern char *str_rchr(const char *str, wchar_t ch); |
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); |
extern bool wstr_remove(wchar_t *str, size_t pos); |
/branches/network/uspace/lib/libc/include/malloc.h |
---|
1,537 → 1,51 |
/* |
Default header file for malloc-2.8.x, written by Doug Lea |
and released to the public domain, as explained at |
http://creativecommons.org/licenses/publicdomain. |
last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee) |
This header is for ANSI C/C++ only. You can set any of |
the following #defines before including: |
* If USE_DL_PREFIX is defined, it is assumed that malloc.c |
was also compiled with this option, so all routines |
have names starting with "dl". |
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this |
file will be #included AFTER <malloc.h>. This is needed only if |
your system defines a struct mallinfo that is incompatible with the |
standard one declared here. Otherwise, you can include this file |
INSTEAD of your system system <malloc.h>. At least on ANSI, all |
declarations should be compatible with system versions |
* If MSPACES is defined, declarations for mspace versions are included. |
* Copyright (c) 2009 Martin Decky |
* 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. |
*/ |
#ifndef MALLOC_280_H |
#define MALLOC_280_H |
#ifdef __cplusplus |
extern "C" { |
#endif |
#include <stddef.h> /* for size_t */ |
#if !ONLY_MSPACES |
#ifndef USE_DL_PREFIX |
#define dlcalloc calloc |
#define dlfree free |
#define dlmalloc malloc |
#define dlmemalign memalign |
#define dlrealloc realloc |
#define dlvalloc valloc |
#define dlpvalloc pvalloc |
#define dlmallinfo mallinfo |
#define dlmallopt mallopt |
#define dlmalloc_trim malloc_trim |
#define dlmalloc_stats malloc_stats |
#define dlmalloc_usable_size malloc_usable_size |
#define dlmalloc_footprint malloc_footprint |
#define dlmalloc_max_footprint malloc_max_footprint |
#define dlindependent_calloc independent_calloc |
#define dlindependent_comalloc independent_comalloc |
#endif /* USE_DL_PREFIX */ |
/* |
malloc(size_t n) |
Returns a pointer to a newly allocated chunk of at least n bytes, or |
null if no space is available, in which case errno is set to ENOMEM |
on ANSI C systems. |
If n is zero, malloc returns a minimum-sized chunk. (The minimum |
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit |
systems.) Note that size_t is an unsigned type, so calls with |
arguments that would be negative if signed are interpreted as |
requests for huge amounts of space, which will often fail. The |
maximum supported value of n differs across systems, but is in all |
cases less than the maximum representable value of a size_t. |
/** @addtogroup libc |
* @{ |
*/ |
void* dlmalloc(size_t); |
/* |
free(void* p) |
Releases the chunk of memory pointed to by p, that had been previously |
allocated using malloc or a related routine such as realloc. |
It has no effect if p is null. If p was not malloced or already |
freed, free(p) will by default cuase the current program to abort. |
/** @file |
*/ |
void dlfree(void*); |
/* |
calloc(size_t n_elements, size_t element_size); |
Returns a pointer to n_elements * element_size bytes, with all locations |
set to zero. |
*/ |
void* dlcalloc(size_t, size_t); |
#ifndef LIBC_MALLOC_H_ |
#define LIBC_MALLOC_H_ |
/* |
realloc(void* p, size_t n) |
Returns a pointer to a chunk of size n that contains the same data |
as does chunk p up to the minimum of (n, p's size) bytes, or null |
if no space is available. |
#include <sys/types.h> |
The returned pointer may or may not be the same as p. The algorithm |
prefers extending p in most cases when possible, otherwise it |
employs the equivalent of a malloc-copy-free sequence. |
extern void __heap_init(void); |
extern uintptr_t get_max_heap_addr(void); |
If p is null, realloc is equivalent to malloc. |
extern void *malloc(const size_t size); |
extern void *memalign(const size_t align, const size_t size); |
extern void *realloc(const void *addr, const size_t size); |
extern void free(const void *addr); |
If space is not available, realloc returns null, errno is set (if on |
ANSI) and p is NOT freed. |
if n is for fewer bytes than already held by p, the newly unused |
space is lopped off and freed if possible. realloc with a size |
argument of zero (re)allocates a minimum-sized chunk. |
The old unix realloc convention of allowing the last-free'd chunk |
to be used as an argument to realloc is not supported. |
*/ |
void* dlrealloc(void*, size_t); |
/* |
memalign(size_t alignment, size_t n); |
Returns a pointer to a newly allocated chunk of n bytes, aligned |
in accord with the alignment argument. |
The alignment argument should be a power of two. If the argument is |
not a power of two, the nearest greater power is used. |
8-byte alignment is guaranteed by normal malloc calls, so don't |
bother calling memalign with an argument of 8 or less. |
Overreliance on memalign is a sure way to fragment space. |
*/ |
void* dlmemalign(size_t, size_t); |
/* |
valloc(size_t n); |
Equivalent to memalign(pagesize, n), where pagesize is the page |
size of the system. If the pagesize is unknown, 4096 is used. |
*/ |
void* dlvalloc(size_t); |
/* |
mallopt(int parameter_number, int parameter_value) |
Sets tunable parameters The format is to provide a |
(parameter-number, parameter-value) pair. mallopt then sets the |
corresponding parameter to the argument value if it can (i.e., so |
long as the value is meaningful), and returns 1 if successful else |
0. SVID/XPG/ANSI defines four standard param numbers for mallopt, |
normally defined in malloc.h. None of these are use in this malloc, |
so setting them has no effect. But this malloc also supports other |
options in mallopt: |
Symbol param # default allowed param values |
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming) |
M_GRANULARITY -2 page size any power of 2 >= page size |
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) |
*/ |
int dlmallopt(int, int); |
#define M_TRIM_THRESHOLD (-1) |
#define M_GRANULARITY (-2) |
#define M_MMAP_THRESHOLD (-3) |
/* |
malloc_footprint(); |
Returns the number of bytes obtained from the system. The total |
number of bytes allocated by malloc, realloc etc., is less than this |
value. Unlike mallinfo, this function returns only a precomputed |
result, so can be called frequently to monitor memory consumption. |
Even if locks are otherwise defined, this function does not use them, |
so results might not be up to date. |
*/ |
size_t dlmalloc_footprint(void); |
size_t dlmalloc_max_footprint(void); |
#if !NO_MALLINFO |
/* |
mallinfo() |
Returns (by copy) a struct containing various summary statistics: |
arena: current total non-mmapped bytes allocated from system |
ordblks: the number of free chunks |
smblks: always zero. |
hblks: current number of mmapped regions |
hblkhd: total bytes held in mmapped regions |
usmblks: the maximum total allocated space. This will be greater |
than current total if trimming has occurred. |
fsmblks: always zero |
uordblks: current total allocated space (normal or mmapped) |
fordblks: total free space |
keepcost: the maximum number of bytes that could ideally be released |
back to system via malloc_trim. ("ideally" means that |
it ignores page restrictions etc.) |
Because these fields are ints, but internal bookkeeping may |
be kept as longs, the reported values may wrap around zero and |
thus be inaccurate. |
*/ |
#ifndef HAVE_USR_INCLUDE_MALLOC_H |
#ifndef _MALLOC_H |
#ifndef MALLINFO_FIELD_TYPE |
#define MALLINFO_FIELD_TYPE size_t |
#endif /* MALLINFO_FIELD_TYPE */ |
struct mallinfo { |
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ |
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ |
MALLINFO_FIELD_TYPE smblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ |
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ |
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ |
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ |
MALLINFO_FIELD_TYPE fordblks; /* total free space */ |
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ |
}; |
#endif /* _MALLOC_H */ |
#endif /* HAVE_USR_INCLUDE_MALLOC_H */ |
struct mallinfo dlmallinfo(void); |
#endif /* NO_MALLINFO */ |
/* |
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); |
independent_calloc is similar to calloc, but instead of returning a |
single cleared space, it returns an array of pointers to n_elements |
independent elements that can hold contents of size elem_size, each |
of which starts out cleared, and can be independently freed, |
realloc'ed etc. The elements are guaranteed to be adjacently |
allocated (this is not guaranteed to occur with multiple callocs or |
mallocs), which may also improve cache locality in some |
applications. |
The "chunks" argument is optional (i.e., may be null, which is |
probably the most typical usage). If it is null, the returned array |
is itself dynamically allocated and should also be freed when it is |
no longer needed. Otherwise, the chunks array must be of at least |
n_elements in length. It is filled in with the pointers to the |
chunks. |
In either case, independent_calloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and "chunks" |
is null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use regular calloc and assign pointers into this |
space to represent elements. (In this case though, you cannot |
independently free elements.) |
independent_calloc simplifies and speeds up implementations of many |
kinds of pools. It may also be useful when constructing large data |
structures that initially have a fixed number of fixed-sized nodes, |
but the number is not known at compile time, and some of the nodes |
may later need to be freed. For example: |
struct Node { int item; struct Node* next; }; |
struct Node* build_list() { |
struct Node** pool; |
int n = read_number_of_nodes_needed(); |
if (n <= 0) return 0; |
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); |
if (pool == 0) die(); |
// organize into a linked list... |
struct Node* first = pool[0]; |
for (i = 0; i < n-1; ++i) |
pool[i]->next = pool[i+1]; |
free(pool); // Can now free the array (or not, if it is needed later) |
return first; |
} |
*/ |
void** dlindependent_calloc(size_t, size_t, void**); |
/* |
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); |
independent_comalloc allocates, all at once, a set of n_elements |
chunks with sizes indicated in the "sizes" array. It returns |
an array of pointers to these elements, each of which can be |
independently freed, realloc'ed etc. The elements are guaranteed to |
be adjacently allocated (this is not guaranteed to occur with |
multiple callocs or mallocs), which may also improve cache locality |
in some applications. |
The "chunks" argument is optional (i.e., may be null). If it is null |
the returned array is itself dynamically allocated and should also |
be freed when it is no longer needed. Otherwise, the chunks array |
must be of at least n_elements in length. It is filled in with the |
pointers to the chunks. |
In either case, independent_comalloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and chunks is |
null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use a single regular malloc, and assign pointers at |
particular offsets in the aggregate space. (In this case though, you |
cannot independently free elements.) |
independent_comallac differs from independent_calloc in that each |
element may have a different size, and also that it does not |
automatically clear elements. |
independent_comalloc can be used to speed up allocation in cases |
where several structs or objects must always be allocated at the |
same time. For example: |
struct Head { ... } |
struct Foot { ... } |
void send_message(char* msg) { |
int msglen = strlen(msg); |
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; |
void* chunks[3]; |
if (independent_comalloc(3, sizes, chunks) == 0) |
die(); |
struct Head* head = (struct Head*)(chunks[0]); |
char* body = (char*)(chunks[1]); |
struct Foot* foot = (struct Foot*)(chunks[2]); |
// ... |
} |
In general though, independent_comalloc is worth using only for |
larger values of n_elements. For small values, you probably won't |
detect enough difference from series of malloc calls to bother. |
Overuse of independent_comalloc can increase overall memory usage, |
since it cannot reuse existing noncontiguous small chunks that |
might be available for some of the elements. |
*/ |
void** dlindependent_comalloc(size_t, size_t*, void**); |
/* |
pvalloc(size_t n); |
Equivalent to valloc(minimum-page-that-holds(n)), that is, |
round up n to nearest pagesize. |
*/ |
void* dlpvalloc(size_t); |
/* |
malloc_trim(size_t pad); |
If possible, gives memory back to the system (via negative arguments |
to sbrk) if there is unused memory at the `high' end of the malloc |
pool or in unused MMAP segments. You can call this after freeing |
large blocks of memory to potentially reduce the system-level memory |
requirements of a program. However, it cannot guarantee to reduce |
memory. Under some allocation patterns, some large free blocks of |
memory will be locked between two used chunks, so they cannot be |
given back to the system. |
The `pad' argument to malloc_trim represents the amount of free |
trailing space to leave untrimmed. If this argument is zero, only |
the minimum amount of memory to maintain internal data structures |
will be left. Non-zero arguments can be supplied to maintain enough |
trailing space to service future expected allocations without having |
to re-obtain memory from the system. |
Malloc_trim returns 1 if it actually released any memory, else 0. |
*/ |
int dlmalloc_trim(size_t); |
/* |
malloc_usable_size(void* p); |
Returns the number of bytes you can actually use in |
an allocated chunk, which may be more than you requested (although |
often not) due to alignment and minimum size constraints. |
You can use this many bytes without worrying about |
overwriting other allocated objects. This is not a particularly great |
programming practice. malloc_usable_size can be more useful in |
debugging and assertions, for example: |
p = malloc(n); |
assert(malloc_usable_size(p) >= 256); |
*/ |
size_t dlmalloc_usable_size(void*); |
/* |
malloc_stats(); |
Prints on stderr the amount of space obtained from the system (both |
via sbrk and mmap), the maximum amount (which may be more than |
current if malloc_trim and/or munmap got called), and the current |
number of bytes allocated via malloc (or realloc, etc) but not yet |
freed. Note that this is the number of bytes allocated, not the |
number requested. It will be larger than the number requested |
because of alignment and bookkeeping overhead. Because it includes |
alignment wastage as being in use, this figure may be greater than |
zero even when no user-level chunks are allocated. |
The reported current and maximum system memory can be inaccurate if |
a program makes other calls to system memory allocation functions |
(normally sbrk) outside of malloc. |
malloc_stats prints only the most commonly interesting statistics. |
More information can be obtained by calling mallinfo. |
*/ |
void dlmalloc_stats(void); |
#endif /* !ONLY_MSPACES */ |
#if MSPACES |
/* |
mspace is an opaque type representing an independent |
region of space that supports mspace_malloc, etc. |
*/ |
typedef void* mspace; |
/* |
create_mspace creates and returns a new independent space with the |
given initial capacity, or, if 0, the default granularity size. It |
returns null if there is no system memory available to create the |
space. If argument locked is non-zero, the space uses a separate |
lock to control access. The capacity of the space will grow |
dynamically as needed to service mspace_malloc requests. You can |
control the sizes of incremental increases of this space by |
compiling with a different DEFAULT_GRANULARITY or dynamically |
setting with mallopt(M_GRANULARITY, value). |
*/ |
mspace create_mspace(size_t capacity, int locked); |
/* |
destroy_mspace destroys the given space, and attempts to return all |
of its memory back to the system, returning the total number of |
bytes freed. After destruction, the results of access to all memory |
used by the space become undefined. |
*/ |
size_t destroy_mspace(mspace msp); |
/* |
create_mspace_with_base uses the memory supplied as the initial base |
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this |
space is used for bookkeeping, so the capacity must be at least this |
large. (Otherwise 0 is returned.) When this initial space is |
exhausted, additional memory will be obtained from the system. |
Destroying this space will deallocate all additionally allocated |
space (if possible) but not the initial base. |
*/ |
mspace create_mspace_with_base(void* base, size_t capacity, int locked); |
/* |
mspace_malloc behaves as malloc, but operates within |
the given space. |
*/ |
void* mspace_malloc(mspace msp, size_t bytes); |
/* |
mspace_free behaves as free, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_free is not actually needed. |
free may be called instead of mspace_free because freed chunks from |
any space are handled by their originating spaces. |
*/ |
void mspace_free(mspace msp, void* mem); |
/* |
mspace_realloc behaves as realloc, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_realloc is not actually |
needed. realloc may be called instead of mspace_realloc because |
realloced chunks from any space are handled by their originating |
spaces. |
*/ |
void* mspace_realloc(mspace msp, void* mem, size_t newsize); |
/* |
mspace_calloc behaves as calloc, but operates within |
the given space. |
*/ |
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); |
/* |
mspace_memalign behaves as memalign, but operates within |
the given space. |
*/ |
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); |
/* |
mspace_independent_calloc behaves as independent_calloc, but |
operates within the given space. |
*/ |
void** mspace_independent_calloc(mspace msp, size_t n_elements, |
size_t elem_size, void* chunks[]); |
/* |
mspace_independent_comalloc behaves as independent_comalloc, but |
operates within the given space. |
*/ |
void** mspace_independent_comalloc(mspace msp, size_t n_elements, |
size_t sizes[], void* chunks[]); |
/* |
mspace_footprint() returns the number of bytes obtained from the |
system for this space. |
*/ |
size_t mspace_footprint(mspace msp); |
#if !NO_MALLINFO |
/* |
mspace_mallinfo behaves as mallinfo, but reports properties of |
the given space. |
*/ |
struct mallinfo mspace_mallinfo(mspace msp); |
#endif /* NO_MALLINFO */ |
/* |
mspace_malloc_stats behaves as malloc_stats, but reports |
properties of the given space. |
*/ |
void mspace_malloc_stats(mspace msp); |
/* |
mspace_trim behaves as malloc_trim, but |
operates within the given space. |
*/ |
int mspace_trim(mspace msp, size_t pad); |
/* |
An alias for mallopt. |
*/ |
int mspace_mallopt(int, int); |
#endif /* MSPACES */ |
#ifdef __cplusplus |
}; /* end of extern "C" */ |
#endif |
#endif /* MALLOC_280_H */ |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/vfs/vfs.h |
---|
55,8 → 55,8 |
extern int mount(const char *, const char *, const char *, const char *, |
unsigned int); |
extern void stdio_init(int filc, fdi_node_t *filv[]); |
extern void stdio_done(void); |
extern void __stdio_init(int filc, fdi_node_t *filv[]); |
extern void __stdio_done(void); |
extern int open_node(fdi_node_t *, int); |
extern int fd_phone(int); |
/branches/network/uspace/lib/libc/include/async.h |
---|
46,11 → 46,7 |
extern atomic_t async_futex; |
static inline void async_manager(void) |
{ |
fibril_switch(FIBRIL_TO_MANAGER); |
} |
extern int __async_init(void); |
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs); |
static inline ipc_callid_t async_get_call(ipc_call_t *data) |
58,6 → 54,11 |
return async_get_call_timeout(data, 0); |
} |
static inline void async_manager(void) |
{ |
fibril_switch(FIBRIL_TO_MANAGER); |
} |
/* |
* User-friendly wrappers for async_send_fast() and async_send_slow(). The |
* macros are in the form async_send_m(), where m denotes the number of payload |
94,7 → 95,6 |
extern void async_usleep(suseconds_t timeout); |
extern void async_create_manager(void); |
extern void async_destroy_manager(void); |
extern int _async_init(void); |
extern void async_set_client_connection(async_client_conn_t conn); |
extern void async_set_interrupt_received(async_client_conn_t conn); |
/branches/network/uspace/lib/libc/include/stdlib.h |
---|
50,6 → 50,7 |
{ |
return random(); |
} |
static inline void srand(unsigned int seed) |
{ |
srandom(seed); |
/branches/network/uspace/lib/libc/include/stdio.h |
---|
37,6 → 37,7 |
#include <sys/types.h> |
#include <stdarg.h> |
#include <string.h> |
#include <adt/list.h> |
#define EOF (-1) |
46,10 → 47,10 |
#define DEBUG(fmt, ...) \ |
{ \ |
char buf[256]; \ |
int n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \ |
if (n > 0) \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, str_size(buf)); \ |
char _buf[256]; \ |
int _n = snprintf(_buf, sizeof(_buf), fmt, ##__VA_ARGS__); \ |
if (_n > 0) \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) _buf, str_size(_buf)); \ |
} |
#ifndef SEEK_SET |
/branches/network/uspace/lib/libc/include/bitops.h |
---|
42,9 → 42,9 |
* |
* If number is zero, it returns 0 |
*/ |
static inline int fnzb32(uint32_t arg) |
static inline unsigned int fnzb32(uint32_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 16) { |
arg >>= 16; |
74,9 → 74,9 |
return n; |
} |
static inline int fnzb64(uint64_t arg) |
static inline unsigned int fnzb64(uint64_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 32) { |
arg >>= 32; |
83,10 → 83,13 |
n += 32; |
} |
return n + fnzb32((uint32_t) arg); |
return (n + fnzb32((uint32_t) arg)); |
} |
#define fnzb(x) fnzb32(x) |
static inline unsigned int fnzb(size_t arg) |
{ |
return fnzb64(arg); |
} |
#endif |
/branches/network/uspace/lib/libc/include/task.h |
---|
39,11 → 39,18 |
typedef uint64_t task_id_t; |
typedef enum { |
TASK_EXIT_NORMAL, |
TASK_EXIT_UNEXPECTED |
} task_exit_t; |
extern task_id_t task_get_id(void); |
extern int task_set_name(const char *name); |
extern task_id_t task_spawn(const char *path, char *const argv[]); |
extern int task_wait(task_id_t id); |
extern int task_wait(task_id_t id, task_exit_t *texit, int *retval); |
extern int task_retval(int val); |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/unistd.h |
---|
65,7 → 65,6 |
extern int chdir(const char *); |
extern void _exit(int status) __attribute__ ((noreturn)); |
extern void *sbrk(ssize_t incr); |
extern int usleep(unsigned long usec); |
extern unsigned int sleep(unsigned int seconds); |
/branches/network/uspace/lib/libc/include/fibril.h |
---|
75,7 → 75,7 |
/** Fibril-local variable specifier */ |
#define fibril_local __thread |
extern int context_save(context_t *c); |
extern int context_save(context_t *c) __attribute__ ((returns_twice)); |
extern void context_restore(context_t *c) __attribute__ ((noreturn)); |
extern fid_t fibril_create(int (*func)(void *), void *arg); |
/branches/network/uspace/lib/libc/include/devmap.h |
---|
47,6 → 47,9 |
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int); |
extern int devmap_device_connect(dev_handle_t, unsigned int); |
extern int devmap_null_create(void); |
extern void devmap_null_destroy(int); |
extern ipcarg_t devmap_device_get_count(void); |
extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *); |
/branches/network/uspace/lib/libc/include/io/console.h |
---|
43,6 → 43,13 |
KEY_RELEASE |
} console_ev_type_t; |
enum { |
CONSOLE_CCAP_NONE = 0, |
CONSOLE_CCAP_STYLE, |
CONSOLE_CCAP_INDEXED, |
CONSOLE_CCAP_RGB |
}; |
/** Console event structure. */ |
typedef struct { |
/** Press or release event. */ |
68,6 → 75,7 |
extern void console_set_rgb_color(int phone, int fg_color, int bg_color); |
extern void console_cursor_visibility(int phone, bool show); |
extern int console_get_color_cap(int phone, int *ccap); |
extern void console_kcon_enable(int phone); |
extern bool console_get_event(int phone, console_event_t *event); |
/branches/network/uspace/lib/libc/include/adt/gcdlcm.h |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2009 Martin Decky |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_GCDLCM_H_ |
#define LIBC_GCDLCM_H_ |
#include <sys/types.h> |
#define DECLARE_GCD(type, name) \ |
static inline type name(type a, type b) \ |
{ \ |
if (a == 0) \ |
return b; \ |
\ |
while (b != 0) { \ |
if (a > b) \ |
a -= b; \ |
else \ |
b -= a; \ |
} \ |
\ |
return a; \ |
} |
#define DECLARE_LCM(type, name, gcd) \ |
static inline type name(type a, type b) \ |
{ \ |
return (a * b) / gcd(a, b); \ |
} |
DECLARE_GCD(uint32_t, gcd32); |
DECLARE_GCD(uint64_t, gcd64); |
DECLARE_GCD(size_t, gcd); |
DECLARE_LCM(uint32_t, lcm32, gcd32); |
DECLARE_LCM(uint64_t, lcm64, gcd64); |
DECLARE_LCM(size_t, lcm, gcd); |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/macros.h |
---|
35,6 → 35,9 |
#ifndef LIBC_MACROS_H_ |
#define LIBC_MACROS_H_ |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
/branches/network/uspace/lib/libc/include/ipc/devmap.h |
---|
48,6 → 48,8 |
DEVMAP_DEVICE_UNREGISTER, |
DEVMAP_DEVICE_GET_NAME, |
DEVMAP_DEVICE_GET_HANDLE, |
DEVMAP_DEVICE_NULL_CREATE, |
DEVMAP_DEVICE_NULL_DESTROY, |
DEVMAP_DEVICE_GET_COUNT, |
DEVMAP_DEVICE_GET_DEVICES |
} devmap_request_t; |
/branches/network/uspace/lib/libc/include/ipc/vfs.h |
---|
57,36 → 57,40 |
} vfs_info_t; |
typedef enum { |
VFS_OPEN_NODE = IPC_FIRST_USER_METHOD, |
VFS_READ, |
VFS_WRITE, |
VFS_TRUNCATE, |
VFS_MOUNT, |
VFS_UNMOUNT, |
VFS_DEVICE, |
VFS_SYNC, |
VFS_CLOSE, |
VFS_LAST_CMN /* keep this the last member of this enum */ |
} vfs_request_cmn_t; |
VFS_IN_OPEN = IPC_FIRST_USER_METHOD, |
VFS_IN_OPEN_NODE, |
VFS_IN_READ, |
VFS_IN_WRITE, |
VFS_IN_SEEK, |
VFS_IN_TRUNCATE, |
VFS_IN_FSTAT, |
VFS_IN_CLOSE, |
VFS_IN_MOUNT, |
VFS_IN_UNMOUNT, |
VFS_IN_SYNC, |
VFS_IN_REGISTER, |
VFS_IN_MKDIR, |
VFS_IN_UNLINK, |
VFS_IN_RENAME, |
VFS_IN_STAT |
} vfs_in_request_t; |
typedef enum { |
VFS_LOOKUP = VFS_LAST_CMN, |
VFS_MOUNTED, |
VFS_DESTROY, |
VFS_LAST_CLNT /* keep this the last member of this enum */ |
} vfs_request_clnt_t; |
VFS_OUT_OPEN_NODE = IPC_FIRST_USER_METHOD, |
VFS_OUT_READ, |
VFS_OUT_WRITE, |
VFS_OUT_TRUNCATE, |
VFS_OUT_CLOSE, |
VFS_OUT_MOUNT, |
VFS_OUT_MOUNTED, |
VFS_OUT_UNMOUNT, |
VFS_OUT_SYNC, |
VFS_OUT_STAT, |
VFS_OUT_LOOKUP, |
VFS_OUT_DESTROY, |
VFS_OUT_LAST |
} vfs_out_request_t; |
typedef enum { |
VFS_REGISTER = VFS_LAST_CMN, |
VFS_OPEN, |
VFS_SEEK, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_RENAME, |
VFS_NODE, |
VFS_LAST_SRV /* keep this the last member of this enum */ |
} vfs_request_srv_t; |
/* |
* Lookup flags. |
*/ |
/branches/network/uspace/lib/libc/include/ipc/ns.h |
---|
39,7 → 39,9 |
typedef enum { |
NS_PING = IPC_FIRST_USER_METHOD, |
NS_TASK_WAIT |
NS_TASK_WAIT, |
NS_ID_INTRO, |
NS_RETVAL |
} ns_request_t; |
#endif |
/branches/network/uspace/lib/libc/include/ipc/console.h |
---|
39,7 → 39,8 |
#include <ipc/vfs.h> |
typedef enum { |
CONSOLE_GET_SIZE = VFS_LAST_SRV, |
CONSOLE_GET_SIZE = VFS_OUT_LAST, |
CONSOLE_GET_COLOR_CAP, |
CONSOLE_GET_EVENT, |
CONSOLE_GOTO, |
CONSOLE_CLEAR, |
/branches/network/uspace/lib/libc/include/ipc/fb.h |
---|
41,6 → 41,7 |
FB_PUTCHAR = IPC_FIRST_USER_METHOD, |
FB_CLEAR, |
FB_GET_CSIZE, |
FB_GET_COLOR_CAP, |
FB_CURSOR_VISIBILITY, |
FB_CURSOR_GOTO, |
FB_SCROLL, |
71,6 → 72,13 |
FB_SCREEN_RECLAIM |
} fb_request_t; |
enum { |
FB_CCAP_NONE = 0, |
FB_CCAP_STYLE, |
FB_CCAP_INDEXED, |
FB_CCAP_RGB |
}; |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/errno.h |
---|
35,12 → 35,13 |
#ifndef LIBC_ERRNO_H_ |
#define LIBC_ERRNO_H_ |
/* TODO: support threads/fibrils */ |
#include <kernel/errno.h> |
#include <fibril.h> |
extern int _errno; |
#define errno _errno |
#include <kernel/errno.h> |
#define EMFILE (-17) |
#define ENAMETOOLONG (-256) |
#define EISDIR (-257) |
/branches/network/uspace/lib/libc/include/sys/stat.h |
---|
36,7 → 36,26 |
#define LIBC_SYS_STAT_H_ |
#include <sys/types.h> |
#include <bool.h> |
#include <ipc/vfs.h> |
#include <ipc/devmap.h> |
struct stat { |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
fs_index_t index; |
unsigned lnkcnt; |
bool is_file; |
off_t size; |
union { |
struct { |
dev_handle_t device; |
} devfs_stat; |
}; |
}; |
extern int fstat(int, struct stat *); |
extern int stat(const char *, struct stat *); |
extern int mkdir(const char *, mode_t); |
#endif |
/branches/network/uspace/lib/libc/generic/task.c |
---|
148,10 → 148,23 |
return 0; |
} |
int task_wait(task_id_t id) |
int task_wait(task_id_t id, task_exit_t *texit, int *retval) |
{ |
return (int) async_req_2_0(PHONE_NS, NS_TASK_WAIT, LOWER32(id), UPPER32(id)); |
ipcarg_t te, rv; |
int rc; |
rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id), |
UPPER32(id), &te, &rv); |
*texit = te; |
*retval = rv; |
return rc; |
} |
int task_retval(int val) |
{ |
return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val); |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/getopt.c |
---|
47,7 → 47,7 |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
const char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
162,7 → 162,7 |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
const char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
275,7 → 275,7 |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
optarg = place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
353,7 → 353,8 |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
char *current_argv; |
const char *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
/branches/network/uspace/lib/libc/generic/as.c |
---|
38,11 → 38,10 |
#include <align.h> |
#include <sys/types.h> |
#include <bitops.h> |
#include <malloc.h> |
/** |
* Either 4*256M on 32-bit architecures or 16*256M on 64-bit architectures. |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t)<<28) |
/** Last position allocated by as_get_mappable_page */ |
static uintptr_t last_allocated = 0; |
/** Create address space area. |
* |
51,6 → 50,7 |
* @param flags Flags describing type of the area. |
* |
* @return address on success, (void *) -1 otherwise. |
* |
*/ |
void *as_area_create(void *address, size_t size, int flags) |
{ |
65,7 → 65,8 |
* @param size New requested size of the area. |
* @param flags Currently unused. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_resize(void *address, size_t size, int flags) |
{ |
78,7 → 79,8 |
* @param address Virtual address pointing into the address space area being |
* destroyed. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_destroy(void *address) |
{ |
91,7 → 93,8 |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
99,101 → 102,29 |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
static void *last_allocated = 0; |
/* Start of heap linker symbol */ |
extern char _heap; |
/** Sbrk emulation |
* |
* @param incr New area that should be allocated or negative, |
if it should be shrinked |
* @return Pointer to newly allocated area |
*/ |
void *sbrk(ssize_t incr) |
{ |
int rc; |
void *res; |
/* Check for invalid values */ |
if ((incr < 0) && (((size_t) -incr) > heapsize)) |
return NULL; |
/* Check for too large value */ |
if ((incr > 0) && (incr + heapsize < heapsize)) |
return NULL; |
/* Check for too small values */ |
if ((incr < 0) && (incr + heapsize > heapsize)) |
return NULL; |
/* Check for user limit */ |
if ((maxheapsize != (size_t) (-1)) && (heapsize + incr) > maxheapsize) |
return NULL; |
rc = as_area_resize(&_heap, heapsize + incr, 0); |
if (rc != 0) |
return NULL; |
/* Compute start of new area */ |
res = (void *) &_heap + heapsize; |
heapsize += incr; |
return res; |
} |
/** Set maximum heap size and return pointer just after the heap */ |
void *set_maxheapsize(size_t mhs) |
{ |
maxheapsize = mhs; |
/* Return pointer to area not managed by sbrk */ |
return ((void *) &_heap + maxheapsize); |
} |
/** Return pointer to some unmapped area, where fits new as_area |
* |
* @param sz Requested size of the allocation. |
* @param size Requested size of the allocation. |
* |
* @return Pointer to the beginning |
* @return pointer to the beginning |
* |
* TODO: make some first_fit/... algorithm, we are now just incrementing |
* the pointer to last area |
*/ |
void *as_get_mappable_page(size_t sz) |
void *as_get_mappable_page(size_t size) |
{ |
void *res; |
uint64_t asz; |
int i; |
if (!sz) |
if (size == 0) |
return NULL; |
asz = 1 << (fnzb64(sz - 1) + 1); |
size_t sz = 1 << (fnzb(size - 1) + 1); |
if (last_allocated == 0) |
last_allocated = get_max_heap_addr(); |
/* Set heapsize to some meaningful value */ |
if (maxheapsize == (size_t) -1) |
set_maxheapsize(MAX_HEAP_SIZE); |
/* |
* Make sure we allocate from naturally aligned address. |
*/ |
i = 0; |
if (!last_allocated) { |
last_allocated = (void *) ALIGN_UP((void *) &_heap + |
maxheapsize, asz); |
} else { |
last_allocated = (void *) ALIGN_UP(((uintptr_t) |
last_allocated) + (int) (i > 0), asz); |
} |
uintptr_t res = ALIGN_UP(last_allocated, sz); |
last_allocated = res + ALIGN_UP(size, PAGE_SIZE); |
res = last_allocated; |
last_allocated += ALIGN_UP(sz, PAGE_SIZE); |
return res; |
return ((void *) res); |
} |
/** @} |
/branches/network/uspace/lib/libc/generic/string.c |
---|
589,7 → 589,7 |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
const char *str_chr(const char *str, wchar_t ch) |
char *str_chr(const char *str, wchar_t ch) |
{ |
wchar_t acc; |
size_t off = 0; |
597,7 → 597,7 |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + last); |
return (char *) (str + last); |
last = off; |
} |
611,7 → 611,7 |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
const char *str_rchr(const char *str, wchar_t ch) |
char *str_rchr(const char *str, wchar_t ch) |
{ |
wchar_t acc; |
size_t off = 0; |
624,7 → 624,7 |
last = off; |
} |
return res; |
return (char *) res; |
} |
/** Insert a wide character into a wide string. |
/branches/network/uspace/lib/libc/generic/malloc.c |
---|
0,0 → 1,475 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Petr Tuma |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <malloc.h> |
#include <bool.h> |
#include <as.h> |
#include <align.h> |
#include <macros.h> |
#include <assert.h> |
#include <errno.h> |
#include <bitops.h> |
#include <mem.h> |
#include <adt/gcdlcm.h> |
/* Magic used in heap headers. */ |
#define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101 |
/* Magic used in heap footers. */ |
#define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202 |
/** Allocation alignment (this also covers the alignment of fields |
in the heap header and footer) */ |
#define BASE_ALIGN 16 |
/** |
* Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28) |
/** |
* |
*/ |
#define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) |
/** |
* Calculate real size of a heap block (with header and footer) |
*/ |
#define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD) |
/** |
* Calculate net size of a heap block (without header and footer) |
*/ |
#define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) |
/** Header of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* Indication of a free block */ |
bool free; |
/* A magic value to detect overwrite of heap header */ |
uint32_t magic; |
} heap_block_head_t; |
/** Footer of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* A magic value to detect overwrite of heap footer */ |
uint32_t magic; |
} heap_block_foot_t; |
/** Linker heap symbol */ |
extern char _heap; |
/** Address of heap start */ |
static void *heap_start = 0; |
/** Address of heap end */ |
static void *heap_end = 0; |
/** Maximum heap size */ |
static size_t max_heap_size = (size_t) -1; |
/** Current number of pages of heap area */ |
static size_t heap_pages = 0; |
/** Initialize a heap block |
* |
* Fills in the structures related to a heap block. |
* |
* @param addr Address of the block. |
* @param size Size of the block including the header and the footer. |
* @param free Indication of a free block. |
* |
*/ |
static void block_init(void *addr, size_t size, bool free) |
{ |
/* Calculate the position of the header and the footer */ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t)); |
head->size = size; |
head->free = free; |
head->magic = HEAP_BLOCK_HEAD_MAGIC; |
foot->size = size; |
foot->magic = HEAP_BLOCK_FOOT_MAGIC; |
} |
/** Check a heap block |
* |
* Verifies that the structures related to a heap block still contain |
* the magic constants. This helps detect heap corruption early on. |
* |
* @param addr Address of the block. |
* |
*/ |
static void block_check(void *addr) |
{ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
assert(head->magic == HEAP_BLOCK_HEAD_MAGIC); |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t)); |
assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC); |
assert(head->size == foot->size); |
} |
static bool grow_heap(size_t size) |
{ |
if (size == 0) |
return false; |
size_t heap_size = (size_t) (heap_end - heap_start); |
if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size)) |
return false; |
size_t pages = (size - 1) / PAGE_SIZE + 1; |
if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0) |
== EOK) { |
void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) + |
(heap_pages + pages) * PAGE_SIZE, BASE_ALIGN); |
block_init(heap_end, end - heap_end, true); |
heap_pages += pages; |
heap_end = end; |
return true; |
} |
return false; |
} |
static void shrink_heap(void) |
{ |
// TODO |
} |
/** Initialize the heap allocator |
* |
* Finds how much physical memory we have and creates |
* the heap management structures that mark the whole |
* physical memory as a single free block. |
* |
*/ |
void __heap_init(void) |
{ |
if (as_area_create((void *) &_heap, PAGE_SIZE, |
AS_AREA_WRITE | AS_AREA_READ)) { |
heap_pages = 1; |
heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN); |
heap_end = |
(void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN); |
/* Make the entire area one large block. */ |
block_init(heap_start, heap_end - heap_start, true); |
} |
} |
uintptr_t get_max_heap_addr(void) |
{ |
if (max_heap_size == (size_t) -1) |
max_heap_size = |
max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE); |
return ((uintptr_t) heap_start + max_heap_size); |
} |
static void split_mark(heap_block_head_t *cur, const size_t size) |
{ |
assert(cur->size >= size); |
/* See if we should split the block. */ |
size_t split_limit = GROSS_SIZE(size); |
if (cur->size > split_limit) { |
/* Block big enough -> split. */ |
void *next = ((void *) cur) + size; |
block_init(next, cur->size - size, true); |
block_init(cur, size, false); |
} else { |
/* Block too small -> use as is. */ |
cur->free = false; |
} |
} |
/** Allocate a memory block |
* |
* @param size The size of the block to allocate. |
* @param align Memory address alignment. |
* |
* @return the address of the block or NULL when not enough memory. |
* |
*/ |
static void *malloc_internal(const size_t size, const size_t align) |
{ |
if (align == 0) |
return NULL; |
size_t falign = lcm(align, BASE_ALIGN); |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); |
bool grown = false; |
void *result; |
loop: |
result = NULL; |
heap_block_head_t *cur = (heap_block_head_t *) heap_start; |
while ((result == NULL) && ((void *) cur < heap_end)) { |
block_check(cur); |
/* Try to find a block that is free and large enough. */ |
if ((cur->free) && (cur->size >= real_size)) { |
/* We have found a suitable block. |
Check for alignment properties. */ |
void *addr = ((void *) cur) + sizeof(heap_block_head_t); |
void *aligned = (void *) ALIGN_UP(addr, falign); |
if (addr == aligned) { |
/* Exact block start including alignment. */ |
split_mark(cur, real_size); |
result = addr; |
} else { |
/* Block start has to be aligned */ |
size_t excess = (size_t) (aligned - addr); |
if (cur->size >= real_size + excess) { |
/* The current block is large enough to fit |
data in including alignment */ |
if ((void *) cur > heap_start) { |
/* There is a block before the current block. |
This previous block can be enlarged to compensate |
for the alignment excess */ |
heap_block_foot_t *prev_foot = |
((void *) cur) - sizeof(heap_block_foot_t); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) cur) - prev_foot->size); |
block_check(prev_head); |
size_t reduced_size = cur->size - excess; |
heap_block_head_t *next_head = ((void *) cur) + excess; |
if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) { |
/* The previous block is not free and there is enough |
space to fill in a new free block between the previous |
and current block */ |
block_init(cur, excess, true); |
} else { |
/* The previous block is free (thus there is no need to |
induce additional fragmentation to the heap) or the |
excess is small, thus just enlarge the previous block */ |
block_init(prev_head, prev_head->size + excess, prev_head->free); |
} |
block_init(next_head, reduced_size, true); |
split_mark(next_head, real_size); |
result = aligned; |
cur = next_head; |
} else { |
/* The current block is the first block on the heap. |
We have to make sure that the alignment excess |
is large enough to fit a new free block just |
before the current block */ |
while (excess < STRUCT_OVERHEAD) { |
aligned += falign; |
excess += falign; |
} |
/* Check for current block size again */ |
if (cur->size >= real_size + excess) { |
size_t reduced_size = cur->size - excess; |
cur = (heap_block_head_t *) (heap_start + excess); |
block_init(heap_start, excess, true); |
block_init(cur, reduced_size, true); |
split_mark(cur, real_size); |
result = aligned; |
} |
} |
} |
} |
} |
/* Advance to the next block. */ |
cur = (heap_block_head_t *) (((void *) cur) + cur->size); |
} |
if ((result == NULL) && (!grown)) { |
if (grow_heap(real_size)) { |
grown = true; |
goto loop; |
} |
} |
return result; |
} |
void *malloc(const size_t size) |
{ |
return malloc_internal(size, BASE_ALIGN); |
} |
void *memalign(const size_t align, const size_t size) |
{ |
if (align == 0) |
return NULL; |
size_t palign = |
1 << (fnzb(max(sizeof(void *), align) - 1) + 1); |
return malloc_internal(size, palign); |
} |
void *realloc(const void *addr, const size_t size) |
{ |
if (addr == NULL) |
return malloc(size); |
/* Calculate the position of the header. */ |
heap_block_head_t *head = |
(heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
void *ptr = NULL; |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN)); |
size_t orig_size = head->size; |
if (orig_size > real_size) { |
/* Shrink */ |
if (orig_size - real_size >= STRUCT_OVERHEAD) { |
/* Split the original block to a full block |
and a tailing free block */ |
block_init((void *) head, real_size, false); |
block_init((void *) head + real_size, |
orig_size - real_size, true); |
shrink_heap(); |
} |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
/* Look at the next block. If it is free and the size is |
sufficient then merge the two. */ |
heap_block_head_t *next_head = |
(heap_block_head_t *) (((void *) head) + head->size); |
if (((void *) next_head < heap_end) && |
(head->size + next_head->size >= real_size) && |
(next_head->free)) { |
block_check(next_head); |
block_init(head, head->size + next_head->size, false); |
split_mark(head, real_size); |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
ptr = malloc(size); |
if (ptr != NULL) { |
memcpy(ptr, addr, NET_SIZE(orig_size)); |
free(addr); |
} |
} |
} |
return ptr; |
} |
/** Free a memory block |
* |
* @param addr The address of the block. |
*/ |
void free(const void *addr) |
{ |
/* Calculate the position of the header. */ |
heap_block_head_t *head |
= (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
/* Mark the block itself as free. */ |
head->free = true; |
/* Look at the next block. If it is free, merge the two. */ |
heap_block_head_t *next_head |
= (heap_block_head_t *) (((void *) head) + head->size); |
if ((void *) next_head < heap_end) { |
block_check(next_head); |
if (next_head->free) |
block_init(head, head->size + next_head->size, true); |
} |
/* Look at the previous block. If it is free, merge the two. */ |
if ((void *) head > heap_start) { |
heap_block_foot_t *prev_foot = |
(heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t)); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) head) - prev_foot->size); |
block_check(prev_head); |
if (prev_head->free) |
block_init(prev_head, prev_head->size + head->size, true); |
} |
shrink_heap(); |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/libc.c |
---|
52,11 → 52,8 |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
int _errno; |
void _exit(int status) |
{ |
thread_exit(status); |
64,9 → 61,10 |
void __main(void *pcb_ptr) |
{ |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
int retval; |
_async_init(); |
__heap_init(); |
__async_init(); |
fibril_t *fibril = fibril_setup(); |
__tcb_set(fibril->tcb); |
79,15 → 77,17 |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
stdio_init(0, NULL); |
__stdio_init(0, NULL); |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
stdio_init(__pcb->filc, __pcb->filv); |
__stdio_init(__pcb->filc, __pcb->filv); |
} |
main(argc, argv); |
stdio_done(); |
retval = main(argc, argv); |
__stdio_done(); |
(void) task_retval(retval); |
} |
void __exit(void) |
/branches/network/uspace/lib/libc/generic/devmap.c |
---|
218,6 → 218,31 |
return phone; |
} |
int devmap_null_create(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return -1; |
ipcarg_t null_id; |
int retval = async_req_0_1(phone, DEVMAP_DEVICE_NULL_CREATE, &null_id); |
if (retval != EOK) |
return -1; |
return (int) null_id; |
} |
void devmap_null_destroy(int null_id) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return; |
async_req_1_0(phone, DEVMAP_DEVICE_NULL_DESTROY, (ipcarg_t) null_id); |
} |
ipcarg_t devmap_device_get_count(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
/branches/network/uspace/lib/libc/generic/async.c |
---|
738,7 → 738,7 |
* |
* @return Zero on success or an error code. |
*/ |
int _async_init(void) |
int __async_init(void) |
{ |
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, |
&conn_hash_table_ops)) { |
/branches/network/uspace/lib/libc/generic/vfs/vfs.c |
---|
38,8 → 38,8 |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <stdio.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
137,7 → 137,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL); |
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
198,7 → 198,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
230,7 → 230,7 |
vfs_connect(); |
ipc_call_t answer; |
aid_t req = async_send_4(vfs_phone, VFS_OPEN_NODE, node->fs_handle, |
aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle, |
node->dev_handle, node->index, oflag, &answer); |
ipcarg_t rc; |
252,7 → 252,7 |
async_serialize_start(); |
vfs_connect(); |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
270,7 → 270,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
297,7 → 297,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
314,96 → 314,116 |
return -1; |
} |
int fd_phone(int fildes) |
int fsync(int fildes) |
{ |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t device; |
ipcarg_t rc = async_req_1_1(vfs_phone, VFS_DEVICE, fildes, &device); |
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return -1; |
return devmap_device_connect((dev_handle_t) device, 0); |
return (int) rc; |
} |
int fd_node(int fildes, fdi_node_t *node) |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t fs_handle; |
ipcarg_t dev_handle; |
ipcarg_t index; |
ipcarg_t rc = async_req_1_3(vfs_phone, VFS_NODE, fildes, &fs_handle, |
&dev_handle, &index); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence, |
&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc == EOK) { |
node->fs_handle = (fs_handle_t) fs_handle; |
node->dev_handle = (dev_handle_t) dev_handle; |
node->index = (fs_index_t) index; |
} |
if (rc != EOK) |
return (off_t) -1; |
return rc; |
return (off_t) newoffs; |
} |
int fsync(int fildes) |
int ftruncate(int fildes, off_t length) |
{ |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_SYNC, fildes); |
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
off_t lseek(int fildes, off_t offset, int whence) |
int fstat(int fildes, struct stat *stat) |
{ |
ipcarg_t rc; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
&newoffs); |
req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL); |
rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return (off_t) -1; |
return (off_t) newoffs; |
return rc; |
} |
int ftruncate(int fildes, off_t length) |
int stat(const char *path, struct stat *stat) |
{ |
ipcarg_t rc; |
aid_t req; |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
req = async_send_0(vfs_phone, VFS_IN_STAT, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
} |
DIR *opendir(const char *dirname) |
{ |
452,7 → 472,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
482,7 → 502,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
529,7 → 549,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
598,5 → 618,34 |
return buf; |
} |
int fd_phone(int fildes) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (!stat.devfs_stat.device) |
return -1; |
return devmap_device_connect(stat.devfs_stat.device, 0); |
} |
int fd_node(int fildes, fdi_node_t *node) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (rc == EOK) { |
node->fs_handle = stat.fs_handle; |
node->dev_handle = stat.dev_handle; |
node->index = stat.index; |
} |
return rc; |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/errno.c |
---|
0,0 → 1,41 |
/* |
* Copyright (c) 2009 Martin Decky |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <errno.h> |
#include <fibril.h> |
int _errno; |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/io/console.c |
---|
69,6 → 69,17 |
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false); |
} |
int console_get_color_cap(int phone, int *ccap) |
{ |
ipcarg_t ccap_tmp; |
int rc; |
rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp); |
*ccap = ccap_tmp; |
return rc; |
} |
void console_kcon_enable(int phone) |
{ |
async_msg_0(phone, CONSOLE_KCON_ENABLE); |
/branches/network/uspace/lib/libc/generic/io/io.c |
---|
89,7 → 89,7 |
static LIST_INITIALIZE(files); |
void stdio_init(int filc, fdi_node_t *filv[]) |
void __stdio_init(int filc, fdi_node_t *filv[]) |
{ |
if (filc > 0) { |
stdin = fopen_node(filv[0], "r"); |
113,7 → 113,7 |
} |
} |
void stdio_done(void) |
void __stdio_done(void) |
{ |
link_t *link = files.next; |
180,6 → 180,23 |
stream->buf_head = stream->buf; |
} |
static void _setvbuf(FILE *stream) |
{ |
/* FIXME: Use more complex rules for setting buffering options. */ |
switch (stream->fd) { |
case 1: |
setvbuf(stream, NULL, _IOLBF, BUFSIZ); |
break; |
case 0: |
case 2: |
setvbuf(stream, NULL, _IONBF, 0); |
break; |
default: |
setvbuf(stream, NULL, _IOFBF, BUFSIZ); |
} |
} |
/** Allocate stream buffer. */ |
static int _fallocbuf(FILE *stream) |
{ |
225,10 → 242,8 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
/* FIXME: Should select buffering type based on what was opened. */ |
setvbuf(stream, NULL, _IOFBF, BUFSIZ); |
list_append(&stream->link, &files); |
return stream; |
248,10 → 263,8 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
/* FIXME: Should select buffering type based on what was opened. */ |
setvbuf(stream, NULL, _IOLBF, BUFSIZ); |
list_append(&stream->link, &files); |
return stream; |
281,10 → 294,8 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
/* FIXME: Should select buffering type based on what was opened. */ |
setvbuf(stream, NULL, _IOLBF, BUFSIZ); |
list_append(&stream->link, &files); |
return stream; |
380,7 → 391,7 |
{ |
size_t bytes_used; |
if (!stream->buf || stream->btype == _IONBF || stream->error) |
if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) |
return; |
bytes_used = stream->buf_head - stream->buf; |
411,8 → 422,11 |
bool need_flush; |
/* If not buffered stream, write out directly. */ |
if (stream->btype == _IONBF) |
return _fwrite(buf, size, nmemb, stream); |
if (stream->btype == _IONBF) { |
now = _fwrite(buf, size, nmemb, stream); |
fflush(stream); |
return now; |
} |
/* Perform lazy allocation of stream buffer. */ |
if (stream->buf == NULL) { |
425,8 → 439,7 |
total_written = 0; |
need_flush = false; |
while (!stream->error && bytes_left > 0) { |
while ((!stream->error) && (bytes_left > 0)) { |
buf_free = stream->buf_size - (stream->buf_head - stream->buf); |
if (bytes_left > buf_free) |
now = buf_free; |
437,7 → 450,7 |
b = data[i]; |
stream->buf_head[i] = b; |
if (b == '\n' && stream->btype == _IOLBF) |
if ((b == '\n') && (stream->btype == _IOLBF)) |
need_flush = true; |
} |
/branches/network/uspace/lib/libc/generic/mman.c |
---|
45,6 → 45,7 |
// if (! ((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE))) |
// return MAP_FAILED; |
if (! (flags & MAP_ANONYMOUS)) |
return MAP_FAILED; |
/branches/network/uspace/lib/libc/Makefile |
---|
49,6 → 49,7 |
generic/cap.c \ |
generic/devmap.c \ |
generic/event.c \ |
generic/errno.c \ |
generic/mem.c \ |
generic/string.c \ |
generic/fibril.c \ |
68,7 → 69,7 |
generic/io/vsnprintf.c \ |
generic/io/printf_core.c \ |
generic/io/console.c \ |
malloc/malloc.c \ |
generic/malloc.c \ |
generic/sysinfo.c \ |
generic/ipc.c \ |
generic/async.c \ |
105,7 → 106,7 |
clean: |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend |
find generic/ arch/$(UARCH)/ malloc -name '*.o' -follow -exec rm \{\} \; |
find generic/ arch/$(UARCH)/ -name '*.o' -follow -exec rm \{\} \; |
depend: kerninc |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
/branches/network/uspace/lib/libc/arch/sparc64/include/stack.h |
---|
45,6 → 45,11 |
*/ |
#define STACK_WINDOW_SAVE_AREA_SIZE (16 * STACK_ITEM_SIZE) |
/* |
* Six extended words for first six arguments. |
*/ |
#define STACK_ARG_SAVE_AREA_SIZE (6 * STACK_ITEM_SIZE) |
/** |
* By convention, the actual top of the stack is %sp + STACK_BIAS. |
*/ |
/branches/network/uspace/lib/libc/arch/sparc64/include/fibril.h |
---|
39,7 → 39,7 |
#include <sys/types.h> |
#include <align.h> |
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE |
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE) |
#ifdef context_set |
#undef context_set |
/branches/network/uspace/lib/libc/arch/ia64/Makefile.inc |
---|
37,7 → 37,7 |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/ddi.c |
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16 |
CFLAGS += -fno-unwind-tables |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
ENDIANESS = LE |
/branches/network/uspace/srv/kbd/ctl/pl050.c |
---|
0,0 → 1,262 |
/* |
* 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 kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief PL050 keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
#include <stdio.h> |
#define PL050_CAPS_SCAN_CODE 0x58 |
#define PL050_NUM_SCAN_CODE 0x77 |
#define PL050_SCROLL_SCAN_CODE 0x7E |
static bool is_lock_key(int); |
enum dec_state { |
ds_s, |
ds_e |
}; |
static enum dec_state ds; |
static int scanmap_simple[] = { |
[0x0e] = KC_BACKTICK, |
[0x16] = KC_1, |
[0x1e] = KC_2, |
[0x26] = KC_3, |
[0x25] = KC_4, |
[0x2e] = KC_5, |
[0x36] = KC_6, |
[0x3d] = KC_7, |
[0x3e] = KC_8, |
[0x46] = KC_9, |
[0x45] = KC_0, |
[0x4e] = KC_MINUS, |
[0x55] = KC_EQUALS, |
[0x66] = KC_BACKSPACE, |
[0x0d] = KC_TAB, |
[0x15] = KC_Q, |
[0x1d] = KC_W, |
[0x24] = KC_E, |
[0x2d] = KC_R, |
[0x2c] = KC_T, |
[0x35] = KC_Y, |
[0x3c] = KC_U, |
[0x43] = KC_I, |
[0x44] = KC_O, |
[0x4d] = KC_P, |
[0x54] = KC_LBRACKET, |
[0x5b] = KC_RBRACKET, |
[0x58] = KC_CAPS_LOCK, |
[0x1c] = KC_A, |
[0x1b] = KC_S, |
[0x23] = KC_D, |
[0x2b] = KC_F, |
[0x34] = KC_G, |
[0x33] = KC_H, |
[0x3b] = KC_J, |
[0x42] = KC_K, |
[0x4b] = KC_L, |
[0x4c] = KC_SEMICOLON, |
[0x52] = KC_QUOTE, |
[0x5d] = KC_BACKSLASH, |
[0x12] = KC_LSHIFT, |
[0x1a] = KC_Z, |
[0x22] = KC_X, |
[0x21] = KC_C, |
[0x2a] = KC_V, |
[0x32] = KC_B, |
[0x31] = KC_N, |
[0x3a] = KC_M, |
[0x41] = KC_COMMA, |
[0x49] = KC_PERIOD, |
[0x4a] = KC_SLASH, |
[0x59] = KC_RSHIFT, |
[0x14] = KC_LCTRL, |
[0x11] = KC_LALT, |
[0x29] = KC_SPACE, |
[0x76] = KC_ESCAPE, |
[0x05] = KC_F1, |
[0x06] = KC_F2, |
[0x04] = KC_F3, |
[0x0c] = KC_F4, |
[0x03] = KC_F5, |
[0x0b] = KC_F6, |
[0x02] = KC_F7, |
[0x0a] = KC_F8, |
[0x01] = KC_F9, |
[0x09] = KC_F10, |
[0x78] = KC_F11, |
[0x07] = KC_F12, |
[0x60] = KC_SCROLL_LOCK, |
[0x5a] = KC_ENTER, |
[0x77] = KC_NUM_LOCK, |
[0x7c] = KC_NTIMES, |
[0x7b] = KC_NMINUS, |
[0x79] = KC_NPLUS, |
[0x6c] = KC_N7, |
[0x75] = KC_N8, |
[0x7d] = KC_N9, |
[0x6b] = KC_N4, |
[0x73] = KC_N5, |
[0x74] = KC_N6, |
[0x69] = KC_N1, |
[0x72] = KC_N2, |
[0x7a] = KC_N3, |
[0x70] = KC_N0, |
[0x71] = KC_NPERIOD |
}; |
static int scanmap_e0[] = { |
[0x65] = KC_RALT, |
[0x59] = KC_RSHIFT, |
[0x64] = KC_PRTSCR, |
[0x70] = KC_INSERT, |
[0x6c] = KC_HOME, |
[0x7d] = KC_PAGE_UP, |
[0x71] = KC_DELETE, |
[0x69] = KC_END, |
[0x7a] = KC_PAGE_DOWN, |
[0x75] = KC_UP, |
[0x6b] = KC_LEFT, |
[0x72] = KC_DOWN, |
[0x74] = KC_RIGHT, |
[0x4a] = KC_NSLASH, |
[0x5a] = KC_NENTER |
}; |
int kbd_ctl_init(void) |
{ |
ds = ds_s; |
return 0; |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
static int key_release_flag = 0; |
static int is_locked = 0; |
console_ev_type_t type; |
unsigned int key; |
int *map; |
size_t map_length; |
if (scancode == 0xe0) { |
ds = ds_e; |
return; |
} |
switch (ds) { |
case ds_s: |
map = scanmap_simple; |
map_length = sizeof(scanmap_simple) / sizeof(int); |
break; |
case ds_e: |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
default: |
map = NULL; |
map_length = 0; |
} |
ds = ds_s; |
if (scancode == 0xf0) { |
key_release_flag = 1; |
return; |
} else { |
if (key_release_flag) { |
type = KEY_RELEASE; |
key_release_flag = 0; |
if (is_lock_key(scancode)) { |
if (!is_locked) { |
is_locked = 1; |
} else { |
is_locked = 0; |
return; |
} |
} |
} else { |
if (is_lock_key(scancode) && is_locked) |
return; |
type = KEY_PRESS; |
} |
} |
if (scancode < 0) |
return; |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
static bool is_lock_key(int sc) |
{ |
return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) || |
(sc == PL050_SCROLL_SCAN_CODE)); |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/kbd/ctl/pc.c |
---|
207,6 → 207,9 |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
default: |
map = NULL; |
map_length = 0; |
} |
ds = ds_s; |
218,7 → 221,7 |
type = KEY_PRESS; |
} |
if (scancode < 0 || scancode >= map_length) |
if ((scancode < 0) || ((size_t) scancode >= map_length)) |
return; |
key = map[scancode]; |
/branches/network/uspace/srv/kbd/port/pl050.c |
---|
0,0 → 1,114 |
/* |
* 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 kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief pl050 port driver. |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <unistd.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
#include <ddi.h> |
#include <stdio.h> |
#define PL050_STAT_RXFULL (1 << 4) |
static irq_cmd_t pl050_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = PL050_STAT_RXFULL, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
static irq_code_t pl050_kbd = { |
sizeof(pl050_cmds) / sizeof(irq_cmd_t), |
pl050_cmds |
}; |
static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
pl050_kbd.cmds[0].addr = (void *) sysinfo_value("kbd.address.status"); |
pl050_kbd.cmds[3].addr = (void *) sysinfo_value("kbd.address.data"); |
async_set_interrupt_received(pl050_irq_handler); |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &pl050_kbd); |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
return; |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/kbd/port/i8042.c |
---|
135,8 → 135,8 |
(void) pio_read_8(&i8042->data); |
/* Enable kbd */ |
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data; |
i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data; |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &i8042_kbd); |
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE; |
/branches/network/uspace/srv/kbd/genarch/gsp.c |
---|
244,7 → 244,7 |
key[0] = t->old_state; |
key[1] = t->input; |
hash_table_insert(&p->trans, &key, &t->link); |
hash_table_insert(&p->trans, key, &t->link); |
} |
/** Allocate transition structure. */ |
276,7 → 276,8 |
gsp_trans_t *t; |
t = hash_table_get_instance(item, gsp_trans_t, link); |
return (key[0] == t->old_state && key[1] == t->input); |
return ((key[0] == (unsigned long) t->old_state) |
&& (key[1] == (unsigned long) t->input)); |
} |
static void trans_op_remove_callback(link_t *item) |
/branches/network/uspace/srv/kbd/Makefile |
---|
61,6 → 61,7 |
endif |
ifeq ($(UARCH), arm32) |
ifeq ($(MACHINE), testarm) |
GENARCH_SOURCES += \ |
port/gxemul.c |
72,6 → 73,12 |
ctl/stty.c |
endif |
endif |
ifeq ($(MACHINE), integratorcp) |
GENARCH_SOURCES += \ |
port/pl050.c \ |
ctl/pl050.c |
endif |
endif |
ifeq ($(UARCH), ia32) |
GENARCH_SOURCES += \ |
/branches/network/uspace/srv/kbd/layout/us_qwerty.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @brief US QWERTY layout. |
* @{ |
*/ |
/branches/network/uspace/srv/kbd/layout/cz.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @brief Czech QWERTZ layout. |
* @{ |
*/ |
399,6 → 399,8 |
case ms_carka: |
return parse_ms_carka(ev); |
} |
return 0; |
} |
/** |
/branches/network/uspace/srv/ns/ns.c |
---|
108,13 → 108,6 |
task_id_t id; |
ipcarg_t retval; |
if (callid & IPC_CALLID_NOTIFICATION) { |
id = (task_id_t) |
MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call)); |
wait_notification((wait_type_t) IPC_GET_ARG1(call), id); |
continue; |
} |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_SHARE_IN: |
switch (IPC_GET_ARG3(call)) { |
133,7 → 126,7 |
} |
continue; |
case IPC_M_PHONE_HUNGUP: |
retval = EOK; |
retval = ns_task_disconnect(&call); |
break; |
case IPC_M_CONNECT_TO_ME: |
/* |
170,6 → 163,12 |
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
wait_for_task(id, &call, callid); |
continue; |
case NS_ID_INTRO: |
retval = ns_task_id_intro(&call); |
break; |
case NS_RETVAL: |
retval = ns_task_retval(&call); |
break; |
default: |
retval = ENOENT; |
break; |
/branches/network/uspace/srv/ns/task.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
41,20 → 42,13 |
#include "ns.h" |
#define TASK_HASH_TABLE_CHAINS 256 |
#define P2I_HASH_TABLE_CHAINS 256 |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id); |
/* TODO: |
* |
* The current implementation of waiting on a task is not perfect. If somebody |
* wants to wait on a task which has already finished before the NS asked |
* the kernel to receive notifications, it would block indefinitively. |
* |
* A solution to this is to fail immediately on a task for which no creation |
* notification was received yet. However, there is a danger of a race condition |
* in this solution -- the caller has to make sure that it is not trying to wait |
* before the NS has a change to receive the task creation notification. This |
* can be assured by waiting for this event in task_spawn(). |
* |
* Finally, as there is currently no convention that each task has to be waited |
* As there is currently no convention that each task has to be waited |
* for, the NS can leak memory because of the zombie tasks. |
* |
*/ |
63,7 → 57,9 |
typedef struct { |
link_t link; |
task_id_t id; /**< Task ID. */ |
bool destroyed; |
bool finished; /**< Task is done. */ |
bool have_rval; /**< Task returned a value. */ |
int retval; /**< The return value. */ |
} hashed_task_t; |
/** Compute hash index into task hash table. |
83,7 → 79,7 |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be lesser or equal to 2. |
* @param keys Must be less than or equal to 2. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
125,6 → 121,65 |
/** Task hash table structure. */ |
static hash_table_t task_hash_table; |
typedef struct { |
link_t link; |
ipcarg_t phash; /**< Task ID. */ |
task_id_t id; /**< Task ID. */ |
} p2i_entry_t; |
/** Compute hash index into task hash table. |
* |
* @param key Array of keys. |
* @return Hash index corresponding to key[0]. |
* |
*/ |
static hash_index_t p2i_hash(unsigned long *key) |
{ |
assert(key); |
return (*key % TASK_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be less than or equal to 1. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
assert(key); |
assert(keys == 1); |
assert(item); |
p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link); |
return (key[0] == e->phash); |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
static void p2i_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, p2i_entry_t, link)); |
} |
/** Operations for task hash table. */ |
static hash_table_operations_t p2i_ops = { |
.hash = p2i_hash, |
.compare = p2i_compare, |
.remove_callback = p2i_remove |
}; |
/** Map phone hash to task ID */ |
static hash_table_t phone_to_id; |
/** Pending task wait structure. */ |
typedef struct { |
link_t link; |
142,8 → 197,11 |
return ENOMEM; |
} |
if (event_subscribe(EVENT_WAIT, 0) != EOK) |
printf(NAME ": Error registering wait notifications\n"); |
if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS, |
1, &p2i_ops)) { |
printf(NAME ": No memory available for tasks\n"); |
return ENOMEM; |
} |
list_initialize(&pending_wait); |
154,6 → 212,7 |
void process_pending_wait(void) |
{ |
link_t *cur; |
task_exit_t texit; |
loop: |
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) { |
169,11 → 228,15 |
continue; |
hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link); |
if (!ht->destroyed) |
if (!ht->finished) |
continue; |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, EOK); |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : |
TASK_EXIT_UNEXPECTED; |
ipc_answer_2(pr->callid, EOK, texit, |
ht->retval); |
} |
hash_table_remove(&task_hash_table, keys, 2); |
list_remove(cur); |
182,27 → 245,11 |
} |
} |
static void fail_pending_wait(task_id_t id, int rc) |
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid) |
{ |
link_t *cur; |
ipcarg_t retval; |
task_exit_t texit; |
loop: |
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) { |
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link); |
if (pr->id == id) { |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, rc); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
} |
void wait_notification(wait_type_t et, task_id_t id) |
{ |
unsigned long keys[2] = { |
LOWER32(id), |
UPPER32(id) |
209,39 → 256,16 |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if (link == NULL) { |
hashed_task_t *ht = |
(hashed_task_t *) malloc(sizeof(hashed_task_t)); |
if (ht == NULL) { |
fail_pending_wait(id, ENOMEM); |
return; |
/* No such task exists. */ |
retval = ENOENT; |
goto out; |
} |
link_initialize(&ht->link); |
ht->id = id; |
ht->destroyed = (et == TASK_CREATE) ? false : true; |
hash_table_insert(&task_hash_table, keys, &ht->link); |
} else { |
hashed_task_t *ht = |
hash_table_get_instance(link, hashed_task_t, link); |
ht->destroyed = (et == TASK_CREATE) ? false : true; |
} |
} |
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid) |
{ |
ipcarg_t retval; |
unsigned long keys[2] = { |
LOWER32(id), |
UPPER32(id) |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if ((ht == NULL) || (!ht->destroyed)) { |
if (!ht->finished) { |
/* Add to pending list */ |
pending_wait_t *pr = |
(pending_wait_t *) malloc(sizeof(pending_wait_t)); |
260,10 → 284,131 |
retval = EOK; |
out: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : TASK_EXIT_UNEXPECTED; |
ipc_answer_2(callid, retval, texit, ht->retval); |
} |
} |
int ns_task_id_intro(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
link_t *link; |
p2i_entry_t *e; |
hashed_task_t *ht; |
id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); |
keys[0] = call->in_phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link != NULL) |
return EEXISTS; |
e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t)); |
if (e == NULL) |
return ENOMEM; |
ht = (hashed_task_t *) malloc(sizeof(hashed_task_t)); |
if (ht == NULL) |
return ENOMEM; |
/* Insert to phone-to-id map. */ |
link_initialize(&e->link); |
e->phash = call->in_phone_hash; |
e->id = id; |
hash_table_insert(&phone_to_id, keys, &e->link); |
/* Insert to main table. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_initialize(&ht->link); |
ht->id = id; |
ht->finished = false; |
ht->have_rval = false; |
ht->retval = -1; |
hash_table_insert(&task_hash_table, keys, &ht->link); |
return EOK; |
} |
int ns_task_retval(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if ((ht == NULL) || ht->finished) |
return EINVAL; |
ht->finished = true; |
ht->have_rval = true; |
ht->retval = IPC_GET_ARG1(*call); |
return EOK; |
} |
int ns_task_disconnect(ipc_call_t *call) |
{ |
unsigned long keys[2]; |
task_id_t id; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
/* Delete from phone-to-id map. */ |
keys[0] = call->in_phone_hash; |
hash_table_remove(&phone_to_id, keys, 1); |
/* Mark task as finished. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = |
hash_table_get_instance(link, hashed_task_t, link); |
if (ht == NULL) |
return EOK; |
ht->finished = true; |
return EOK; |
} |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id) |
{ |
unsigned long keys[1]; |
link_t *link; |
p2i_entry_t *e; |
keys[0] = phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link == NULL) |
return ENOENT; |
e = hash_table_get_instance(link, p2i_entry_t, link); |
*id = e->id; |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/ns/task.h |
---|
42,6 → 42,11 |
extern void wait_notification(wait_type_t et, task_id_t id); |
extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid); |
extern int ns_task_id_intro(ipc_call_t *call); |
extern int ns_task_disconnect(ipc_call_t *call); |
extern int ns_task_retval(ipc_call_t *call); |
#endif |
/** |
/branches/network/uspace/srv/console/screenbuffer.h |
---|
135,6 → 135,8 |
return (a1.a.r.fg_color == a2.a.r.fg_color) |
&& (a1.a.r.bg_color == a2.a.r.bg_color); |
} |
return 0; |
} |
/branches/network/uspace/srv/console/console.c |
---|
69,6 → 69,7 |
int phone; /**< Framebuffer phone */ |
ipcarg_t cols; /**< Framebuffer columns */ |
ipcarg_t rows; /**< Framebuffer rows */ |
int color_cap; /**< Color capabilities (FB_CCAP_xxx) */ |
} fb_info; |
typedef struct { |
172,6 → 173,19 |
} |
} |
static int ccap_fb_to_con(int ccap_fb, int *ccap_con) |
{ |
switch (ccap_fb) { |
case FB_CCAP_NONE: *ccap_con = CONSOLE_CCAP_NONE; break; |
case FB_CCAP_STYLE: *ccap_con = CONSOLE_CCAP_STYLE; break; |
case FB_CCAP_INDEXED: *ccap_con = CONSOLE_CCAP_INDEXED; break; |
case FB_CCAP_RGB: *ccap_con = CONSOLE_CCAP_RGB; break; |
default: return EINVAL; |
} |
return EOK; |
} |
/** Send an area of screenbuffer to the FB driver. */ |
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height) |
{ |
527,6 → 541,9 |
ipcarg_t arg2; |
ipcarg_t arg3; |
int cons_ccap; |
int rc; |
async_serialize_start(); |
if (cons->refcount == 0) |
gcons_notify_connect(cons->index); |
551,17 → 568,17 |
if (cons->refcount == 0) |
gcons_notify_disconnect(cons->index); |
return; |
case VFS_READ: |
case VFS_OUT_READ: |
async_serialize_end(); |
cons_read(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
async_serialize_end(); |
cons_write(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
fb_pending_flush(); |
if (cons == active_console) { |
async_req_0_0(fb_info.phone, FB_FLUSH); |
588,6 → 605,14 |
arg1 = fb_info.cols; |
arg2 = fb_info.rows; |
break; |
case CONSOLE_GET_COLOR_CAP: |
rc = ccap_fb_to_con(fb_info.color_cap, &cons_ccap); |
if (rc != EOK) { |
ipc_answer_0(callid, rc); |
continue; |
} |
arg1 = cons_ccap; |
break; |
case CONSOLE_SET_STYLE: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
639,6 → 664,8 |
static bool console_init(void) |
{ |
ipcarg_t color_cap; |
/* Connect to keyboard driver */ |
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
if (kbd_phone < 0) { |
674,6 → 701,8 |
/* Synchronize, the gcons could put something in queue */ |
async_req_0_0(fb_info.phone, FB_FLUSH); |
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows); |
async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &color_cap); |
fb_info.color_cap = color_cap; |
/* Set up shared memory buffer. */ |
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; |
/branches/network/uspace/srv/bd/file_bd/file_bd.c |
---|
49,6 → 49,7 |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#define NAME "file_bd" |
86,6 → 87,7 |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
/branches/network/uspace/srv/bd/gxe_bd/gxe_bd.c |
---|
46,6 → 46,7 |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <task.h> |
#define NAME "gxe_bd" |
110,6 → 111,7 |
return -1; |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
/branches/network/uspace/srv/bd/ata_bd/ata_bd.c |
---|
54,6 → 54,7 |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#include "ata_bd.h" |
95,7 → 96,9 |
return -1; |
/* Put drives to reset, disable interrupts. */ |
printf("Reset drives...\n"); |
printf("Reset drives... "); |
fflush(stdout); |
pio_write_8(&ctl->device_control, DCR_SRST); |
/* FIXME: Find out how to do this properly. */ |
async_usleep(100); |
106,8 → 109,6 |
} while ((status & SR_BSY) != 0); |
printf("Done\n"); |
printf("Status = 0x%x\n", pio_read_8(&cmd->status)); |
(void) drive_identify(0, &disk[0]); |
(void) drive_identify(1, &disk[1]); |
135,6 → 136,7 |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
147,13 → 149,14 |
uint8_t status; |
size_t i; |
printf("Identify drive %d\n", disk_id); |
printf("Identify drive %d... ", disk_id); |
fflush(stdout); |
pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0)); |
async_usleep(100); |
pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); |
status = pio_read_8(&cmd->status); |
printf("Status = 0x%x\n", status); |
d->present = false; |
/branches/network/uspace/srv/loader/main.c |
---|
52,6 → 52,8 |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/loader.h> |
#include <ipc/ns.h> |
#include <macros.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
437,15 → 439,23 |
int main(int argc, char *argv[]) |
{ |
ipcarg_t phonead; |
task_id_t id; |
int rc; |
connected = false; |
/* Introduce this task to the NS (give it our task ID). */ |
id = task_get_id(); |
rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id)); |
if (rc != EOK) |
return -1; |
/* Set a handler of incomming connections. */ |
async_set_client_connection(ldr_connection); |
/* Register at naming service. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) |
return -1; |
return -2; |
async_manager(); |
/branches/network/uspace/srv/fb/serial_console.c |
---|
388,6 → 388,10 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED : |
FB_CCAP_STYLE); |
continue; |
case FB_CLEAR: |
serial_clrscr(); |
retval = 0; |
/branches/network/uspace/srv/fb/fb.c |
---|
56,6 → 56,8 |
#include <async.h> |
#include <fibril.h> |
#include <bool.h> |
#include <stdio.h> |
#include <byteorder.h> |
#include "font-8x16.h" |
#include "fb.h" |
211,9 → 213,9 |
unsigned int row); |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) |
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
225,36 → 227,58 |
#define BB_POS(vport, col, row) ((row) * vport->cols + (col)) |
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline) |
/** ARGB 8:8:8:8 conversion |
/* |
* RGB conversion and mask functions. |
* |
* These functions write an RGB value to some memory in some predefined format. |
* The naming convention corresponds to the format created by these functions. |
* The functions use the so called network order (i.e. big endian) with respect |
* to their names. |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = rgb & 0x00ffffff; |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8))); |
} |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8))); |
} |
static void mask_0888(void *dst, bool mask) |
{ |
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0); |
bgr_0888(dst, mask ? 0xffffff : 0); |
} |
static void rgb_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0); |
} |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
static void bgr_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0); |
} |
static void mask_8880(void *dst, bool mask) |
{ |
bgr_8880(dst, mask ? 0xffffff : 0); |
} |
/** RGB 8:8:8 conversion |
* |
*/ |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
262,63 → 286,44 |
static void mask_888(void *dst, bool mask) |
{ |
if (mask) { |
((uint8_t *) dst)[0] = 0xff; |
((uint8_t *) dst)[1] = 0xff; |
((uint8_t *) dst)[2] = 0xff; |
} else { |
((uint8_t *) dst)[0] = 0; |
((uint8_t *) dst)[1] = 0; |
((uint8_t *) dst)[2] = 0; |
bgr_888(dst, mask ? 0xffffff : 0); |
} |
static void rgb_555_be(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
} |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
static void rgb_555_le(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
} |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
static void rgb_565_be(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
} |
static void mask_555(void *dst, bool mask) |
static void rgb_565_le(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = (mask ? 0x7fff : 0); |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
} |
/** RGB 5:6:5 conversion |
* |
*/ |
static void rgb_565(void *dst, uint32_t rgb) |
static void mask_555(void *dst, bool mask) |
{ |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
rgb_555_be(dst, mask ? 0xffffff : 0); |
} |
static void mask_565(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0xffff : 0); |
rgb_565_be(dst, mask ? 0xffffff : 0); |
} |
/** RGB 3:2:3 |
* |
*/ |
static void rgb_323(void *dst, uint32_t rgb) |
static void bgr_323(void *dst, uint32_t rgb) |
{ |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
326,7 → 331,7 |
static void mask_323(void *dst, bool mask) |
{ |
*((uint8_t *) dst) = (mask ? 0xff : 0); |
bgr_323(dst, mask ? 0x0 : ~0x0); |
} |
/** Draw a filled rectangle. |
620,24 → 625,32 |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb_conv = rgb_323; |
screen.rgb_conv = bgr_323; |
screen.mask_conv = mask_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb_conv = rgb_555; |
case VISUAL_RGB_5_5_5_LE: |
screen.rgb_conv = rgb_555_le; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb_conv = rgb_565; |
case VISUAL_RGB_5_5_5_BE: |
screen.rgb_conv = rgb_555_be; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_LE: |
screen.rgb_conv = rgb_565_le; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_BE: |
screen.rgb_conv = rgb_565_be; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
649,8 → 662,8 |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.rgb_conv = rgb_8880; |
screen.mask_conv = mask_8880; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
663,6 → 676,11 |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_8_8_8_0: |
screen.rgb_conv = bgr_8880; |
screen.mask_conv = mask_8880; |
screen.pixelbytes = 4; |
break; |
default: |
return false; |
} |
1067,10 → 1085,11 |
if (IPC_GET_ARG1(*call) == shm_id) { |
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
shm_size = IPC_GET_ARG2(*call); |
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) { |
shm_id = 0; |
return false; |
} |
shm = dest; |
else |
shm_id = 0; |
if (shm[0] != 'P') |
return false; |
1645,6 → 1664,9 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, vport->cols, vport->rows); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_RGB); |
continue; |
case FB_SCROLL: |
scroll = IPC_GET_ARG1(call); |
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) { |
/branches/network/uspace/srv/fb/ppm.c |
---|
89,7 → 89,7 |
{ |
unsigned int width, height; |
unsigned int maxcolor; |
unsigned i; |
unsigned int i; |
unsigned int color; |
unsigned int coef; |
/branches/network/uspace/srv/fb/ega.c |
---|
319,6 → 319,9 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_INDEXED); |
continue; |
case FB_CLEAR: |
clrscr(); |
retval = 0; |
/branches/network/uspace/srv/fs/devfs/devfs.c |
---|
67,37 → 67,37 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_MOUNTED: |
case VFS_OUT_MOUNTED: |
devfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
devfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
devfs_lookup(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
devfs_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
devfs_device(callid, &call); |
case VFS_OUT_STAT: |
devfs_stat(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
devfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
devfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
devfs_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_CLOSE: |
devfs_close(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
devfs_sync(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
devfs_destroy(callid, &call); |
break; |
default: |
/branches/network/uspace/srv/fs/devfs/devfs_ops.c |
---|
43,6 → 43,7 |
#include <libfs.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <sys/stat.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
163,12 → 164,12 |
if (first >= last) { |
/* Root entry */ |
if (lflag & L_DIRECTORY) |
if (!(lflag & L_FILE)) |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0); |
else |
ipc_answer_0(rid, ENOENT); |
} else { |
if (lflag & L_FILE) { |
if (!(lflag & L_DIRECTORY)) { |
size_t len; |
if (last >= first) |
len = last - first + 1; |
277,10 → 278,30 |
ipc_answer_3(rid, EOK, 0, 1, L_FILE); |
} |
void devfs_device(ipc_callid_t rid, ipc_call_t *request) |
void devfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size) || |
size != sizeof(struct stat)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
struct stat stat; |
memset(&stat, 0, sizeof(struct stat)); |
stat.fs_handle = devfs_reg.fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = 1; |
stat.is_file = (index != 0); |
stat.size = 0; |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
288,16 → 309,13 |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
if (lnk != NULL) |
stat.devfs_stat.device = (dev_handle_t)index; |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_1(rid, EOK, (ipcarg_t) index); |
} else |
ipc_answer_0(rid, ENOTSUP); |
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
void devfs_read(ipc_callid_t rid, ipc_call_t *request) |
/branches/network/uspace/srv/fs/devfs/devfs_ops.h |
---|
42,7 → 42,7 |
extern void devfs_mount(ipc_callid_t, ipc_call_t *); |
extern void devfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void devfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void devfs_device(ipc_callid_t, ipc_call_t *); |
extern void devfs_stat(ipc_callid_t, ipc_call_t *); |
extern void devfs_sync(ipc_callid_t, ipc_call_t *); |
extern void devfs_read(ipc_callid_t, ipc_call_t *); |
extern void devfs_write(ipc_callid_t, ipc_call_t *); |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.h |
---|
86,10 → 86,10 |
extern void tmpfs_read(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_write(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_stat(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_close(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_device(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *); |
extern bool tmpfs_restore(dev_handle_t); |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
67,8 → 67,8 |
tmpfs_node_t *nodep; |
uint32_t size; |
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry), |
TMPFS_BLOCK_SIZE) != EOK) |
if (block_seqread(dev, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
87,7 → 87,7 |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
if (block_seqread(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy(fn); |
free(fname); |
103,7 → 103,7 |
} |
free(fname); |
if (block_read(dev, bufpos, buflen, pos, &size, |
if (block_seqread(dev, bufpos, buflen, pos, &size, |
sizeof(size), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
115,7 → 115,7 |
return false; |
nodep->size = size; |
if (block_read(dev, bufpos, buflen, pos, nodep->data, |
if (block_seqread(dev, bufpos, buflen, pos, nodep->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
return false; |
131,7 → 131,7 |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
if (block_seqread(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy(fn); |
free(fname); |
174,7 → 174,7 |
off_t pos = 0; |
char tag[6]; |
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5, |
if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE) != EOK) |
goto error; |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.c |
---|
98,37 → 98,37 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_MOUNTED: |
case VFS_OUT_MOUNTED: |
tmpfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
tmpfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
tmpfs_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
tmpfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
tmpfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
tmpfs_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_CLOSE: |
tmpfs_close(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
tmpfs_destroy(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
tmpfs_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
tmpfs_device(callid, &call); |
case VFS_OUT_STAT: |
tmpfs_stat(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
tmpfs_sync(callid, &call); |
break; |
default: |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
628,9 → 628,9 |
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_device(ipc_callid_t rid, ipc_call_t *request) |
void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request) |
/branches/network/uspace/srv/fs/fat/fat.h |
---|
207,10 → 207,11 |
extern void fat_read(ipc_callid_t, ipc_call_t *); |
extern void fat_write(ipc_callid_t, ipc_call_t *); |
extern void fat_truncate(ipc_callid_t, ipc_call_t *); |
extern void fat_stat(ipc_callid_t, ipc_call_t *); |
extern void fat_close(ipc_callid_t, ipc_call_t *); |
extern void fat_destroy(ipc_callid_t, ipc_call_t *); |
extern void fat_open_node(ipc_callid_t, ipc_call_t *); |
extern void fat_device(ipc_callid_t, ipc_call_t *); |
extern void fat_stat(ipc_callid_t, ipc_call_t *); |
extern void fat_sync(ipc_callid_t, ipc_call_t *); |
extern fat_idx_t *fat_idx_get_new(dev_handle_t); |
/branches/network/uspace/srv/fs/fat/fat.c |
---|
91,37 → 91,37 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_MOUNTED: |
case VFS_OUT_MOUNTED: |
fat_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
fat_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
fat_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
fat_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
fat_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_STAT: |
fat_stat(callid, &call); |
break; |
case VFS_OUT_CLOSE: |
fat_close(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
fat_destroy(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
fat_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
fat_device(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
fat_sync(callid, &call); |
break; |
default: |
/branches/network/uspace/srv/fs/fat/fat_ops.c |
---|
402,7 → 402,7 |
fat_dentry_t *d; |
fat_bs_t *bs; |
block_t *b; |
int i, j; |
unsigned i, j; |
uint16_t bps; |
unsigned dps; |
unsigned blocks; |
1202,9 → 1202,9 |
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_device(ipc_callid_t rid, ipc_call_t *request) |
void fat_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_sync(ipc_callid_t rid, ipc_call_t *request) |
/branches/network/uspace/srv/pci/update-ids |
---|
1,6 → 1,6 |
#! /bin/bash |
wget http://pciids.sourceforge.net/v2.2/pci.ids |
wget -O pci.ids http://pciids.sourceforge.net/v2.2/pci.ids |
cat > pci_ids.h <<EOF |
/* DO NOT EDIT, THIS FILE IS AUTOMATICALLY GENERATED */ |
7,7 → 7,8 |
char *pci_ids[] = { |
EOF |
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | sed -n 's/\(.*\)/"\1",/p' >> pci_ids.h |
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | \ |
sed -n 's/\(.*\)/"\1",/p' | sed 's/?/\\?/g' >> pci_ids.h |
cat >> pci_ids.h <<EOF |
"" |
/branches/network/uspace/srv/pci/libpci/i386-ports.c |
---|
79,14 → 79,14 |
d.func = 0; |
for (d.dev = 0; d.dev < 32; d.dev++) { |
u16 class, vendor; |
if (m->read(&d, PCI_CLASS_DEVICE, (byte *) & class, |
if ((m->read(&d, PCI_CLASS_DEVICE, (byte *) & class, |
sizeof(class)) |
&& (class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST) |
|| class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA)) |
|| m->read(&d, PCI_VENDOR_ID, (byte *) & vendor, |
|| class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA))) |
|| (m->read(&d, PCI_VENDOR_ID, (byte *) & vendor, |
sizeof(vendor)) |
&& (vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL) |
|| vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ))) { |
|| vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ)))) { |
a->debug("...outside the Asylum at 0/%02x/0", |
d.dev); |
return 1; |
/branches/network/uspace/srv/pci/libpci/pci_ids.h |
---|
386,7 → 386,7 |
" 1043 c01b A9600XT/TD (Secondary)", |
" 174b 7c28 Sapphire Radeon 9600XT (Secondary)", |
" 1787 4003 Radeon 9600 XT (Secondary)", |
" 4173 RV350 ?? [Radeon 9550] (Secondary)", |
" 4173 RV350 \?\? [Radeon 9550] (Secondary)", |
" 4237 Radeon 7000 IGP", |
" 4242 R200 BB [Radeon All in Wonder 8500DV]", |
" 1002 02aa Radeon 8500 AIW DV Edition", |
668,7 → 668,7 |
" 1002 002a Rage 128 Pro AIW AGP", |
" 1002 0048 Rage Fury Pro", |
" 1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device)", |
" 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)", |
" 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device\?!)", |
" 5047 Rage 128 PG/PRO", |
" 5048 Rage 128 PH/PRO AGP 2x", |
" 5049 Rage 128 PI/PRO AGP 4x", |
1635,7 → 1635,7 |
" 1028 0106 PowerEdge 4600", |
" 1028 0121 PowerEdge 2650", |
"102b Matrox Graphics, Inc.", |
" 0010 MGA-I [Impression?]", |
" 0010 MGA-I [Impression\?]", |
" 0100 MGA 1064SG [Mystique]", |
" 0518 MGA-II [Athena]", |
" 0519 MGA 2064W [Millennium]", |
2437,7 → 2437,7 |
" 9922 W99200F/W9922PF MPEG-1/2 Video Encoder", |
" 9970 W9970CF", |
"1051 Anigma, Inc.", |
"1052 ?Young Micro Systems", |
"1052 \?Young Micro Systems", |
"1053 Young Micro Systems", |
"1054 Hitachi, Ltd", |
"1055 Efar Microsystems", |
3048,7 → 3048,7 |
" 0369 Bt878 Video Capture", |
" 1002 0001 TV-Wonder", |
" 1002 0003 TV-Wonder/VE", |
" 036c Bt879(??) Video Capture", |
" 036c Bt879(\?\?) Video Capture", |
" 13e9 0070 Win/TV (Video Section)", |
" 036e Bt878 Video Capture", |
" 0070 13eb WinTV Series", |
4123,7 → 4123,7 |
" 01de Quadro FX 350", |
" 10de 01dc Quadro FX Go350M", |
" 01df GeForce 7300 GS", |
" 01e0 nForce2 AGP (different version?)", |
" 01e0 nForce2 AGP (different version\?)", |
" 147b 1c09 NV7 Motherboard", |
" 01e8 nForce2 AGP", |
" 01ea nForce2 Memory Controller 0", |
5096,7 → 5096,7 |
" 1113 1211 EN-1207D Fast Ethernet Adapter", |
" 1216 EN-1216 Ethernet Adapter", |
" 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card", |
" 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]", |
" 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX \?]", |
" 1217 EN-1217 Ethernet Adapter", |
" 5105 10Mbps Network card", |
" 9211 EN-1207D Fast Ethernet Adapter", |
6556,7 → 6556,7 |
"123e Simutech, Inc.", |
"123f C-Cube Microsystems", |
" 00e4 MPEG", |
" 8120 E4?", |
" 8120 E4\?", |
" 11bd 0006 DV500 E4", |
" 11bd 000a DV500 E4", |
" 11bd 000f DV500 E4", |
6632,7 → 6632,7 |
" 0640 Aries 16000P", |
"125d ESS Technology", |
" 0000 ES336H Fax Modem (Early Model)", |
" 1948 Solo?", |
" 1948 Solo\?", |
" 1968 ES1968 Maestro 2", |
" 1028 0085 ES1968 Maestro-2 PCI", |
" 1033 8051 ES1968 Maestro-2 Audiodrive", |
6922,7 → 6922,7 |
" 122d 4056 MSP3880SP-U", |
" 122d 4057 MSP3880SP-A", |
" 4311 Riptide HSF 56k PCI Modem", |
" 127a 4311 Ring Modular? Riptide HSF RT HP Dom", |
" 127a 4311 Ring Modular\? Riptide HSF RT HP Dom", |
" 13e0 0210 HP-GVC", |
" 4320 Riptide PCI Audio Controller", |
" 1235 4320 Riptide PCI Audio Controller", |
8382,7 → 8382,7 |
" 4325 BCM43xG 802.11b/g", |
" 1414 0003 Wireless Notebook Adapter MN-720", |
" 1414 0004 Wireless PCI Adapter MN-730", |
" 4326 BCM4307 Chipcommon I/O Controller?", |
" 4326 BCM4307 Chipcommon I/O Controller\?", |
" 4401 BCM4401 100Base-T", |
" 1043 80a8 A7V8X motherboard", |
" 4402 BCM4402 Integrated 10/100BaseT", |
8691,7 → 8691,7 |
"1504 KAISER Electronics", |
"1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH", |
"1506 CHAMELEON Systems Inc", |
"1507 Motorola ?? / HTEC", |
"1507 Motorola \?\? / HTEC", |
" 0001 MPC105 [Eagle]", |
" 0002 MPC106 [Grackle]", |
" 0003 MPC8240 [Kahlua]", |
9467,7 → 9467,7 |
"270b Xantel Corporation", |
"270f Chaintech Computer Co. Ltd", |
"2711 AVID Technology Inc.", |
"2a15 3D Vision(???)", |
"2a15 3D Vision(\?\?\?)", |
"3000 Hansol Electronics Inc.", |
"3142 Post Impression Systems.", |
"3388 Hint Corp", |
/branches/network/uspace/srv/pci/libpci/names.c |
---|
150,7 → 150,7 |
int cat = -1; |
int nest; |
static const char parse_error[] = "Parse error"; |
int i; |
size_t i; |
*lino = 0; |
for (i = 0; i < sizeof(pci_ids) / sizeof(char *); i++) { |
330,7 → 330,7 |
iv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", iv); |
else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) |
else if ((v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) != 0) |
return (char *) v->name; |
else |
res = snprintf(buf, size, "Unknown vendor %04x", iv); |
340,7 → 340,7 |
id = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", id); |
else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) |
else if ((d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) != 0) |
return (char *) d->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown device %04x", id); |
370,7 → 370,7 |
isv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isv); |
else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) |
else if ((v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) != 0) |
return (char *) v->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown vendor %04x", isv); |
384,7 → 384,7 |
isd = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isd); |
else if (d = id_lookup_subsys(a, iv, id, isv, isd)) |
else if ((d = id_lookup_subsys(a, iv, id, isv, isd)) != 0) |
return (char *) d->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown device %04x", isd); |
415,9 → 415,9 |
icls = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", icls); |
else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) |
else if ((cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) != 0) |
return (char *) cls->name; |
else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) |
else if ((cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) != 0) |
res = snprintf(buf, size, "%s [%04x]", cls->name, icls); |
else if (synth) |
res = snprintf(buf, size, "Class %04x", icls); |
429,7 → 429,7 |
ipif = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%02x", ipif); |
else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) |
else if ((pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) != 0) |
return (char *) pif->name; |
else if (icls == 0x0101 && !(ipif & 0x70)) { |
/* IDE controllers have complex prog-if semantics */ |
/branches/network/uspace/srv/pci/libpci/generic.c |
---|
29,7 → 29,7 |
for (dev = 0; dev < 32; dev++) { |
t->dev = dev; |
multi = 0; |
for (t->func = 0; !t->func || multi && t->func < 8; |
for (t->func = 0; !t->func || (multi && t->func < 8); |
t->func++) { |
u32 vd = pci_read_long(t, PCI_VENDOR_ID); |
struct pci_dev *d; |
/branches/network/uspace/srv/devmap/devmap.c |
---|
47,6 → 47,7 |
#include <ipc/devmap.h> |
#define NAME "devmap" |
#define NULL_DEVICES 256 |
/** Representation of device driver. |
* |
97,8 → 98,10 |
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv); |
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex); |
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex); |
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex); |
static dev_handle_t last_handle = 0; |
static devmap_device_t *null_devices[NULL_DEVICES]; |
static dev_handle_t devmap_create_handle(void) |
{ |
543,12 → 546,12 |
ipc_answer_0(iid, EOK); |
size_t name_size = str_size(device->name); |
/* FIXME: |
* We have no channel from DEVMAP to client, therefore |
* sending must be initiated by client. |
* |
* size_t name_size = str_size(device->name); |
* |
* int rc = ipc_data_write_send(phone, device->name, name_size); |
* if (rc != EOK) { |
* async_wait_for(req, NULL); |
618,21 → 621,43 |
ipc_answer_1(iid, EOK, pos); |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init(void) |
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
unsigned int i; |
bool fnd = false; |
for (i = 0; i < NULL_DEVICES; i++) { |
if (null_devices[i] == NULL) { |
fnd = true; |
break; |
} |
} |
if (!fnd) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* Create NULL device entry */ |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) |
return false; |
if (device == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
device->name = str_dup("null"); |
char null[DEVMAP_NAME_MAXLEN]; |
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i); |
device->name = str_dup(null); |
if (device->name == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
free(device); |
return false; |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
list_initialize(&(device->devices)); |
644,11 → 669,50 |
device->handle = devmap_create_handle(); |
device->driver = NULL; |
/* Insert device into list of all devices */ |
/* Insert device into list of all devices |
and into null devices array */ |
list_append(&device->devices, &devices_list); |
null_devices[i] = device; |
fibril_mutex_unlock(&devices_list_mutex); |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_1(iid, EOK, (ipcarg_t) i); |
} |
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
ipcarg_t i = IPC_GET_ARG1(*icall); |
if (null_devices[i] == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
devmap_device_unregister_core(null_devices[i]); |
null_devices[i] = NULL; |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, EOK); |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init(void) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
unsigned int i; |
for (i = 0; i < NULL_DEVICES; i++) |
null_devices[i] = NULL; |
fibril_mutex_unlock(&null_devices_mutex); |
return true; |
} |
701,7 → 765,7 |
} |
} |
if (NULL != driver) { |
if (driver != NULL) { |
/* |
* Unregister the device driver and all its devices. |
*/ |
733,6 → 797,12 |
case DEVMAP_DEVICE_GET_NAME: |
devmap_get_name(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_CREATE: |
devmap_null_create(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_DESTROY: |
devmap_null_destroy(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_COUNT: |
devmap_get_count(callid, &call); |
break; |
/branches/network/uspace/srv/vfs/vfs.c |
---|
79,52 → 79,52 |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
break; |
case VFS_REGISTER: |
case VFS_IN_REGISTER: |
vfs_register(callid, &call); |
keep_on_going = false; |
break; |
case VFS_MOUNT: |
case VFS_IN_MOUNT: |
vfs_mount(callid, &call); |
break; |
case VFS_OPEN: |
case VFS_IN_OPEN: |
vfs_open(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_IN_OPEN_NODE: |
vfs_open_node(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_IN_CLOSE: |
vfs_close(callid, &call); |
break; |
case VFS_READ: |
case VFS_IN_READ: |
vfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_IN_WRITE: |
vfs_write(callid, &call); |
break; |
case VFS_SEEK: |
case VFS_IN_SEEK: |
vfs_seek(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_IN_TRUNCATE: |
vfs_truncate(callid, &call); |
break; |
case VFS_MKDIR: |
case VFS_IN_FSTAT: |
vfs_fstat(callid, &call); |
break; |
case VFS_IN_STAT: |
vfs_stat(callid, &call); |
break; |
case VFS_IN_MKDIR: |
vfs_mkdir(callid, &call); |
break; |
case VFS_UNLINK: |
case VFS_IN_UNLINK: |
vfs_unlink(callid, &call); |
break; |
case VFS_RENAME: |
case VFS_IN_RENAME: |
vfs_rename(callid, &call); |
break; |
case VFS_DEVICE: |
vfs_device(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_IN_SYNC: |
vfs_sync(callid, &call); |
break; |
case VFS_NODE: |
vfs_node(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
/branches/network/uspace/srv/vfs/vfs_ops.c |
---|
108,7 → 108,7 |
/* |
* Now we hold a reference to mp_node. |
* It will be dropped upon the corresponding VFS_UNMOUNT. |
* It will be dropped upon the corresponding VFS_IN_UNMOUNT. |
* This prevents the mount point from being deleted. |
*/ |
} else { |
121,7 → 121,7 |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
msg = async_send_1(phone, VFS_MOUNTED, |
msg = async_send_1(phone, VFS_OUT_MOUNTED, |
(ipcarg_t) dev_handle, &answer); |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, |
183,7 → 183,7 |
assert(mountee_phone >= 0); |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
msg = async_send_4(phone, VFS_MOUNT, |
msg = async_send_4(phone, VFS_OUT_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
306,7 → 306,7 |
} |
/* Check the offered options size. */ |
if (size < 0 || size > MAX_MNTOPTS_LEN) { |
if (size > MAX_MNTOPTS_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
437,8 → 437,8 |
/* |
* The POSIX interface is open(path, oflag, mode). |
* We can receive oflags and mode along with the VFS_OPEN call; the path |
* will need to arrive in another call. |
* We can receive oflags and mode along with the VFS_IN_OPEN call; |
* the path will need to arrive in another call. |
* |
* We also receive one private, non-POSIX set of flags called lflag |
* used to pass information to vfs_lookup_internal(). |
448,6 → 448,9 |
int mode = IPC_GET_ARG3(*request); |
size_t len; |
/* Ignore mode for now. */ |
(void) mode; |
/* |
* Make sure that we are called with exactly one of L_FILE and |
* L_DIRECTORY. Make sure that the user does not pass L_OPEN. |
555,7 → 558,7 |
* file is being opened and that a file structure is pointing to it. |
* It is necessary so that the file will not disappear when |
* vfs_node_put() is called. The reference will be dropped by the |
* respective VFS_CLOSE. |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
632,7 → 635,7 |
* file is being opened and that a file structure is pointing to it. |
* It is necessary so that the file will not disappear when |
* vfs_node_put() is called. The reference will be dropped by the |
* respective VFS_CLOSE. |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
641,55 → 644,6 |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle, |
file->node->index); |
} |
void vfs_device(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* |
* Lock the open file structure so that no other thread can manipulate |
* the same open file at a time. |
*/ |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_DEVICE request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer)); |
} |
void vfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
708,11 → 662,11 |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_SYMC request at the destination FS server. */ |
/* Make a VFS_OUT_SYMC request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev_handle, |
file->node->index, &answer); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
742,11 → 696,11 |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_CLOSE request at the destination FS server. */ |
/* Make a VFS_OUT_CLOSE request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle, |
file->node->index, &answer); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
832,7 → 786,7 |
ipc_call_t answer; |
if (!read && file->append) |
file->pos = file->node->size; |
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request), |
msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, |
file->node->dev_handle, file->node->index, file->pos, &answer); |
/* |
946,7 → 900,7 |
int fs_phone; |
fs_phone = vfs_grab_phone(fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle, |
rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle, |
(ipcarg_t)index, (ipcarg_t)size); |
vfs_release_phone(fs_phone); |
return (int)rc; |
976,6 → 930,106 |
ipc_answer_0(rid, (ipcarg_t)rc); |
} |
void vfs_fstat(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
size_t size = IPC_GET_ARG2(*request); |
ipcarg_t rc; |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
if (!ipc_data_read_receive(&callid, NULL)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
aid_t msg; |
msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle, |
file->node->index, true, NULL); |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, rc); |
} |
void vfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
size_t len; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
free(path); |
return; |
} |
path[len] = '\0'; |
if (!ipc_data_read_receive(&callid, NULL)) { |
free(path); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
vfs_lookup_res_t lr; |
fibril_rwlock_read_lock(&namespace_rwlock); |
rc = vfs_lookup_internal(path, L_NONE, &lr, NULL); |
free(path); |
if (rc != EOK) { |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(callid, rc); |
ipc_answer_0(rid, rc); |
return; |
} |
vfs_node_t *node = vfs_node_get(&lr); |
if (!node) { |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fibril_rwlock_read_unlock(&namespace_rwlock); |
int fs_phone = vfs_grab_phone(node->fs_handle); |
aid_t msg; |
msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev_handle, |
node->index, false, NULL); |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
ipcarg_t rv; |
async_wait_for(msg, &rv); |
vfs_release_phone(fs_phone); |
ipc_answer_0(rid, rv); |
vfs_node_put(node); |
} |
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request) |
{ |
int mode = IPC_GET_ARG1(*request); |
1002,6 → 1056,9 |
} |
path[len] = '\0'; |
/* Ignore mode for now. */ |
(void) mode; |
fibril_rwlock_write_lock(&namespace_rwlock); |
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE; |
rc = vfs_lookup_internal(path, lflag, NULL, NULL); |
1050,7 → 1107,7 |
/* |
* The name has already been unlinked by vfs_lookup_internal(). |
* We have to get and put the VFS node to ensure that it is |
* VFS_DESTROY'ed after the last reference to it is dropped. |
* VFS_OUT_DESTROY'ed after the last reference to it is dropped. |
*/ |
vfs_node_t *node = vfs_node_get(&lr); |
fibril_mutex_lock(&nodes_mutex); |
/branches/network/uspace/srv/vfs/vfs.h |
---|
198,14 → 198,15 |
extern void vfs_mount(ipc_callid_t, ipc_call_t *); |
extern void vfs_open(ipc_callid_t, ipc_call_t *); |
extern void vfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void vfs_device(ipc_callid_t, ipc_call_t *); |
extern void vfs_sync(ipc_callid_t, ipc_call_t *); |
extern void vfs_node(ipc_callid_t, ipc_call_t *); |
extern void vfs_close(ipc_callid_t, ipc_call_t *); |
extern void vfs_read(ipc_callid_t, ipc_call_t *); |
extern void vfs_write(ipc_callid_t, ipc_call_t *); |
extern void vfs_seek(ipc_callid_t, ipc_call_t *); |
extern void vfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void vfs_fstat(ipc_callid_t, ipc_call_t *); |
extern void vfs_fstat(ipc_callid_t, ipc_call_t *); |
extern void vfs_stat(ipc_callid_t, ipc_call_t *); |
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *); |
extern void vfs_unlink(ipc_callid_t, ipc_call_t *); |
extern void vfs_rename(ipc_callid_t, ipc_call_t *); |
/branches/network/uspace/srv/vfs/vfs_node.c |
---|
129,7 → 129,7 |
*/ |
int phone = vfs_grab_phone(node->fs_handle); |
ipcarg_t rc; |
rc = async_req_2_0(phone, VFS_DESTROY, |
rc = async_req_2_0(phone, VFS_OUT_DESTROY, |
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
assert(rc == EOK); |
vfs_release_phone(phone); |
/branches/network/uspace/srv/vfs/vfs_lookup.c |
---|
159,7 → 159,7 |
ipc_call_t answer; |
int phone = vfs_grab_phone(root->fs_handle); |
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first, |
aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (ipcarg_t) first, |
(ipcarg_t) (first + len - 1) % PLB_SIZE, |
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index, |
&answer); |
204,7 → 204,7 |
int phone = vfs_grab_phone(result->triplet.fs_handle); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, VFS_OPEN_NODE, |
aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE, |
(ipcarg_t) result->triplet.dev_handle, |
(ipcarg_t) result->triplet.index, &answer); |
/branches/network/HelenOS.config |
---|
55,6 → 55,11 |
@ "serengeti" Serengeti system |
! [PLATFORM=sparc64] MACHINE (choice) |
% Machine type |
@ "testarm" GXEmul Testarm |
@ "integratorcp" Integratorcp |
! [PLATFORM=arm32] MACHINE (choice) |
% CPU type |
@ "pentium4" Pentium 4 |
@ "pentium3" Pentium 3 |
325,8 → 330,12 |
% Input device class |
@ "generic" Keyboard or serial line |
! [PLATFORM=arm32&MACHINE=integratorcp] CONFIG_HID_IN (choice) |
% Input device class |
@ "generic" Keyboard or serial line |
@ "none" No input device |
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice) |
! [PLATFORM=ia32|(PLATFORM=arm32&MACHINE=testarm)|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice) |
% Input device class |
@ "generic" Keyboard or serial line |
337,6 → 346,10 |
% Output device class |
@ "generic" Monitor or serial line |
! [PLATFORM=arm32&MACHINE=integratorcp] CONFIG_HID_OUT (choice) |
% Output device class |
@ "generic" Monitor or serial line |
@ "none" No output device |
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ppc32|(PLATFORM=ia64&MACHINE=i460GX)|(PLATFORM=mips32&MACHINE=msim)] CONFIG_HID_OUT (choice) |
352,7 → 365,7 |
@ "monitor" Monitor |
@ "serial" Serial line |
@ "none" No output device |
! [PLATFORM=arm32] CONFIG_HID_OUT (choice) |
! [PLATFORM=arm32&MACHINE=testarm] CONFIG_HID_OUT (choice) |
% PC keyboard support |
! [CONFIG_HID_IN=generic&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_PC_KBD (y/n) |
367,10 → 380,10 |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=mips32] CONFIG_MIPS_PRN (y/n) |
% Support for GXemul keyboard |
! [CONFIG_HID_IN=generic&PLATFORM=arm32] CONFIG_ARM_KBD (y/n) |
! [CONFIG_HID_IN=generic&PLATFORM=arm32&MACHINE=testarm] CONFIG_ARM_KBD (y/n) |
% Support for GXemul printer |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32] CONFIG_ARM_PRN (y/n) |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=testarm] CONFIG_ARM_PRN (y/n) |
% Support for VIA CUDA controller |
! [CONFIG_HID_IN=generic&PLATFORM=ppc32] CONFIG_VIA_CUDA (y/n) |
390,12 → 403,18 |
% Support for Serengeti keyboard |
! [CONFIG_HID_IN=generic&PLATFORM=sparc64&MACHINE=serengeti] CONFIG_SGCN_KBD (y/n) |
% i8042 controller support |
% Support for i8042 controller |
! [CONFIG_PC_KBD=y] CONFIG_I8042 (y) |
% Support for pl050 controller |
! [CONFIG_HID_IN=generic&PLATFORM=arm32&MACHINE=integratorcp] CONFIG_PL050 (y) |
% Sun keyboard support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic&(CONFIG_NS16550=y|CONFIG_Z8530=y)] CONFIG_SUN_KBD (y) |
% Macintosh ADB keyboard support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=ppc32&(CONFIG_VIA_CUDA=y)] CONFIG_MAC_KBD (y) |
% Dummy serial line input |
! [CONFIG_MIPS_KBD=y|CONFIG_ARM_KBD=y] CONFIG_DSRLNIN (y) |
457,6 → 476,12 |
% External ramdisk |
! [PLATFORM=sparc64] CONFIG_RD_EXTERNAL (y/n) |
% Load disk drivers on startup |
! CONFIG_START_BD (n/y) |
% Mount /data on startup |
! [CONFIG_START_BD=y] CONFIG_MOUNT_DATA (n/y) |
% Networking architecture |
@ "modular" Modular |
@ "module" One module |
/branches/network/boot/arch/arm32/loader/_link.ld.in |
---|
17,6 → 17,9 |
*(COMMON); /* global variables */ |
*(.reginfo); |
. = 0x2000; |
*(ST); /* bootloader stack section */ |
. = 0x4000; |
*(PT); /* page table placed at 0x4000 */ |
[[COMPONENTS]] |
/branches/network/boot/arch/arm32/loader/boot.S |
---|
34,8 → 34,10 |
.global start |
.global jump_to_kernel |
.global page_table |
.global boot_stack |
start: |
ldr sp, =boot_stack |
b bootstrap |
jump_to_kernel: |
46,6 → 48,10 |
# |
bx r0 |
#bootloader stack |
.section ST |
.space 4096 |
boot_stack: |
# place page_table to PT section |
.section PT |
/branches/network/boot/arch/arm32/loader/main.c |
---|
67,7 → 67,7 |
/** Prints bootloader version information. */ |
static void version_print(void) |
{ |
printf("HelenOS ARM32 Bootloader\nRelease %s%s%s\nCopyright (c) 2007 HelenOS project\n", |
printf("HelenOS ARM32 Bootloader\nRelease %s%s%s\nCopyright (c) 2009 HelenOS project\n", |
release, revision, timestamp); |
} |
91,8 → 91,6 |
bootinfo.cnt = 0; |
unsigned int i, j; |
for (i = 0; i < COMPONENTS; i++) { |
printf(" %L: %s image (size %d bytes)\n", |
components[i].start, components[i].name, components[i].size); |
top = ALIGN_UP(top, KERNEL_PAGE_SIZE); |
if (i > 0) { |
bootinfo.tasks[bootinfo.cnt].addr = ((void *) KERNEL_VIRTUAL_ADDRESS) + top; |
106,18 → 104,17 |
j = bootinfo.cnt - 1; |
printf("\nCopying components\n"); |
printf("Component\tAddress\t\tSize (Bytes)\n"); |
printf("============================================\n"); |
for (i = COMPONENTS - 1; i > 0; i--, j--) { |
printf(" %s...", components[i].name); |
printf("%s\t\t0x%x\t%d\n", components[i].name, bootinfo.tasks[j].addr, components[i].size); |
memcpy((void *)bootinfo.tasks[j].addr, components[i].start, |
components[i].size); |
printf("done.\n"); |
} |
printf("KERNEL\t\t0x%x\t%d\n", KERNEL_VIRTUAL_ADDRESS, components[0].size); |
printf("\nCopying kernel..."); |
memcpy((void *)KERNEL_VIRTUAL_ADDRESS, components[0].start, |
components[0].size); |
printf("done.\n"); |
printf("\nBooting the kernel...\n"); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo); |
/branches/network/boot/arch/arm32/loader/print/gxemul.c |
---|
File deleted |
/branches/network/boot/arch/arm32/loader/print/print.c |
---|
0,0 → 1,80 |
/* |
* 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 arm32boot |
* @{ |
*/ |
/** @file |
* @brief bootloader output logic |
*/ |
#include <printf.h> |
/** Address where characters to be printed are expected. */ |
#ifdef MACHINE_testarm |
#define PUTC_ADDRESS 0x10000000 |
#endif |
#ifdef MACHINE_integratorcp |
#define PUTC_ADDRESS 0x16000000 |
#endif |
/** Prints a character to the console. |
* |
* @param ch Character to be printed. |
*/ |
static void putc(char ch) |
{ |
if (ch == '\n') |
*((volatile char *) PUTC_ADDRESS) = '\r'; |
*((volatile char *) PUTC_ADDRESS) = ch; |
} |
/** Prints a string to the console. |
* |
* @param str String to be printed. |
* @param len Number of characters to be printed. |
*/ |
void write(const char *str, const int len) |
{ |
int i; |
for (i = 0; i < len; ++i) { |
putc(str[i]); |
} |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/network/boot/arch/arm32/loader/Makefile |
---|
64,7 → 64,7 |
boot.S \ |
asm.S \ |
mm.c \ |
print/gxemul.c \ |
print/print.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
92,8 → 92,11 |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/bd/file_bd/file_bd \ |
$(USPACEDIR)/srv/bd/file_bd/file_bd |
ifeq ($(MACHINE),testarm) |
RD_SRVS += \ |
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd |
endif |
RD_APPS = \ |
$(USPACEDIR)/app/getvc/getvc \ |
/branches/network/version |
---|
36,7 → 36,7 |
VERSION = 0 |
PATCHLEVEL = 4 |
SUBLEVEL = 0 |
SUBLEVEL = 1 |
ifdef EXTRAVERSION |
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL).$(EXTRAVERSION) |
44,4 → 44,4 |
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) |
endif |
NAME = Sinister Valentine |
NAME = Escalopino |
/branches/network/defaults/sparc64/Makefile.config |
---|
54,3 → 54,9 |
# External ramdisk |
CONFIG_RD_EXTERNAL = y |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/ia64/Makefile.config |
---|
42,3 → 42,9 |
# Output device class |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/arm32/Makefile.config |
---|
30,3 → 30,9 |
# What is your output device? |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/arm32/GXemul/Makefile.config |
---|
0,0 → 1,2 |
# Machine type |
MACHINE = testarm |
/branches/network/defaults/arm32/integratorcp/Makefile.config |
---|
0,0 → 1,2 |
# Machine type |
MACHINE = integratorcp |
/branches/network/defaults/ppc32/Makefile.config |
---|
36,3 → 36,9 |
# Use Block Address Translation by the loader |
CONFIG_BAT = y |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/amd64/Makefile.config |
---|
54,3 → 54,9 |
# Default framebuffer depth |
CONFIG_VESA_BPP = 16 |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/mips32/Makefile.config |
---|
36,3 → 36,9 |
# Output device class |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/network/defaults/ia32/Makefile.config |
---|
60,3 → 60,9 |
# Default framebuffer depth |
CONFIG_VESA_BPP = 16 |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |