Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4581 → Rev 4580

/branches/network/uspace/srv/bd/file_bd/Makefile
File deleted
/branches/network/uspace/srv/bd/file_bd/file_bd.c
File deleted
/branches/network/uspace/srv/bd/rd/rd.c
File deleted
/branches/network/uspace/srv/bd/rd/Makefile
File deleted
/branches/network/uspace/srv/bd/gxe_bd/gxe_bd.c
File deleted
/branches/network/uspace/srv/bd/gxe_bd/Makefile
File deleted
/branches/network/uspace/srv/bd/ata_bd/ata_bd.c
File deleted
/branches/network/uspace/srv/bd/ata_bd/Makefile
File deleted
/branches/network/uspace/srv/bd/ata_bd/ata_bd.h
File deleted
/branches/network/uspace/srv/cir/fhc/Makefile
File deleted
/branches/network/uspace/srv/cir/fhc/fhc.c
File deleted
/branches/network/uspace/srv/cir/obio/obio.c
File deleted
Property changes:
Deleted: svn:mergeinfo
/branches/network/uspace/srv/cir/obio/Makefile
File deleted
/branches/network/uspace/srv/cir/obio
Property changes:
Deleted: svn:mergeinfo
/branches/network/uspace/srv/kbd/include/keybuffer.h
File deleted
/branches/network/uspace/srv/kbd/include/layout.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,12 → 37,12
#ifndef KBD_LAYOUT_H_
#define KBD_LAYOUT_H_
 
#include <kbd/kbd.h>
#include <sys/types.h>
#include <io/console.h>
 
typedef struct {
void (*reset)(void);
wchar_t (*parse_ev)(console_event_t *);
wchar_t (*parse_ev)(kbd_event_t *);
} layout_op_t;
 
extern layout_op_t us_qwerty_op;
53,4 → 53,5
 
/**
* @}
*/
*/
 
/branches/network/uspace/srv/kbd/include/key_buffer.h
0,0 → 1,65
/*
* Copyright (c) 2006 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.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef __KEY_BUFFER_H__
#define __KEY_BUFFER_H__
 
#include <sys/types.h>
#include <kbd/kbd.h>
 
/** Size of buffer for pressed keys */
#define KEYBUFFER_SIZE 128
 
typedef struct {
kbd_event_t fifo[KEYBUFFER_SIZE];
unsigned long head;
unsigned long tail;
unsigned long items;
} keybuffer_t;
 
extern void keybuffer_free(keybuffer_t *);
extern void keybuffer_init(keybuffer_t *);
extern int keybuffer_available(keybuffer_t *);
extern int keybuffer_empty(keybuffer_t *);
extern void keybuffer_push(keybuffer_t *, const kbd_event_t *);
extern int keybuffer_pop(keybuffer_t *, kbd_event_t *);
 
#endif
 
/**
* @}
*/
 
/branches/network/uspace/srv/kbd/include/gsp.h
37,7 → 37,7
#ifndef KBD_GSP_H_
#define KBD_GSP_H_
 
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
enum {
GSP_END = -1, /**< Terminates a sequence. */
/branches/network/uspace/srv/kbd/include/kbd.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,20 → 37,14
#ifndef KBD_KBD_H_
#define KBD_KBD_H_
 
#include <keybuffer.h>
#include <ipc/ipc.h>
#include <key_buffer.h>
 
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
 
typedef enum {
KBD_YIELD = IPC_FIRST_USER_METHOD,
KBD_RECLAIM
} kbd_request_t;
 
extern int cir_service;
extern int cir_phone;
 
61,4 → 55,5
 
/**
* @}
*/
*/
 
/branches/network/uspace/srv/kbd/include/kbd_port.h
38,8 → 38,6
#define KBD_PORT_H_
 
extern int kbd_port_init(void);
extern void kbd_port_yield(void);
extern void kbd_port_reclaim(void);
 
#endif
 
/branches/network/uspace/srv/kbd/port/ns16550.c
106,14 → 106,6
return pio_enable((void *) ns16550_physical, 8, &vaddr);
}
 
void ns16550_port_yield(void)
{
}
 
void ns16550_port_reclaim(void)
{
}
 
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
int scan_code = IPC_GET_ARG2(*call);
/branches/network/uspace/srv/kbd/port/sun.c
62,13 → 62,5
return -1;
}
 
void kbd_port_yield(void)
{
}
 
void kbd_port_reclaim(void)
{
}
 
/** @}
*/
/branches/network/uspace/srv/kbd/port/z8530.c
95,14 → 95,6
return 0;
}
 
void z8530_port_yield(void)
{
}
 
void z8530_port_reclaim(void)
{
}
 
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
int scan_code = IPC_GET_ARG2(*call);
/branches/network/uspace/srv/kbd/port/gxemul.c
69,14 → 69,6
return 0;
}
 
void kbd_port_yield(void)
{
}
 
void kbd_port_reclaim(void)
{
}
 
/** Process data sent when a key is pressed.
*
* @param keybuffer Buffer of pressed keys.
/branches/network/uspace/srv/kbd/port/msim.c
69,17 → 69,22
return 0;
}
 
void kbd_port_yield(void)
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
}
int scan_code = IPC_GET_ARG2(*call);
// static int esc_count=0;
 
void kbd_port_reclaim(void)
{
}
// if (scan_code == 0x1b) {
// esc_count++;
// if (esc_count == 3)
// __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
// } else {
// esc_count=0;
// }
 
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
int scan_code = IPC_GET_ARG2(*call);
// if (fb_fb)
// return kbd_arch_process_fb(keybuffer, scan_code);
 
kbd_push_scancode(scan_code);
}
 
/branches/network/uspace/srv/kbd/port/i8042.c
151,14 → 151,6
return 0;
}
 
void kbd_port_yield(void)
{
}
 
void kbd_port_reclaim(void)
{
}
 
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
int status = IPC_GET_ARG1(*call);
/branches/network/uspace/srv/kbd/port/ski.c
42,7 → 42,6
#include <kbd_port.h>
#include <sys/types.h>
#include <thread.h>
#include <bool.h>
 
#define SKI_GETCHAR 21
 
51,8 → 50,6
static void *ski_thread_impl(void *arg);
static int32_t ski_getchar(void);
 
static volatile bool polling_disabled = false;
 
/** Initialize Ski port driver. */
int kbd_port_init(void)
{
67,16 → 64,6
return 0;
}
 
void kbd_port_yield(void)
{
polling_disabled = true;
}
 
void kbd_port_reclaim(void)
{
polling_disabled = false;
}
 
/** Thread to poll Ski for keypresses. */
static void *ski_thread_impl(void *arg)
{
84,7 → 71,7
(void) arg;
 
while (1) {
while (polling_disabled == false) {
while (1) {
c = ski_getchar();
if (c == 0)
break;
/branches/network/uspace/srv/kbd/port/sgcn.c
42,7 → 42,6
#include <sysinfo.h>
#include <stdio.h>
#include <thread.h>
#include <bool.h>
 
#define POLL_INTERVAL 10000
 
93,7 → 92,6
/* polling thread */
static void *sgcn_thread_impl(void *arg);
 
static volatile bool polling_disabled = false;
 
/**
* Initializes the SGCN driver.
122,16 → 120,6
return 0;
}
 
void kbd_port_yield(void)
{
polling_disabled = true;
}
 
void kbd_port_reclaim(void)
{
polling_disabled = false;
}
 
/**
* Handler of the "key pressed" event. Reads codes of all the pressed keys from
* the buffer.
166,11 → 154,11
(void) arg;
 
while (1) {
if (polling_disabled == false)
sgcn_key_pressed();
sgcn_key_pressed();
usleep(POLL_INTERVAL);
}
}
 
 
/** @}
*/
/branches/network/uspace/srv/kbd/port/dummy.c
42,13 → 42,5
return 0;
}
 
void kbd_port_yield(void)
{
}
 
void kbd_port_reclaim(void)
{
}
 
/** @}
*/
/branches/network/uspace/srv/kbd/generic/keybuffer.c
File deleted
/branches/network/uspace/srv/kbd/generic/kbd.c
28,10 → 28,10
 
/**
* @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
45,12 → 45,12
#include <ipc/ns.h>
#include <async.h>
#include <errno.h>
#include <adt/fifo.h>
#include <io/console.h>
#include <io/keycode.h>
#include <libadt/fifo.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
 
#include <kbd.h>
#include <keybuffer.h>
#include <key_buffer.h>
#include <kbd_port.h>
#include <kbd_ctl.h>
#include <layout.h>
88,7 → 88,7
 
void kbd_push_ev(int type, unsigned int key)
{
console_event_t ev;
kbd_event_t ev;
unsigned mod_mask;
 
switch (key) {
102,7 → 102,7
}
 
if (mod_mask != 0) {
if (type == KEY_PRESS)
if (type == KE_PRESS)
mods = mods | mod_mask;
else
mods = mods & ~mod_mask;
116,7 → 116,7
}
 
if (mod_mask != 0) {
if (type == KEY_PRESS) {
if (type == KE_PRESS) {
/*
* Only change lock state on transition from released
* to pressed. This prevents autorepeat from messing
133,7 → 133,7
printf("mods: 0x%x\n", mods);
printf("keycode: %u\n", key);
*/
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F1) {
active_layout = 0;
layout[active_layout]->reset();
140,7 → 140,7
return;
}
 
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F2) {
active_layout = 1;
layout[active_layout]->reset();
147,7 → 147,7
return;
}
 
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F3) {
active_layout = 2;
layout[active_layout]->reset();
193,14 → 193,6
phone2cons = IPC_GET_ARG5(call);
retval = 0;
break;
case KBD_YIELD:
kbd_port_yield();
retval = 0;
break;
case KBD_RECLAIM:
kbd_port_reclaim();
retval = 0;
break;
default:
retval = EINVAL;
}
/branches/network/uspace/srv/kbd/generic/key_buffer.c
0,0 → 1,117
/*
* Copyright (c) 2006 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.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
#include <key_buffer.h>
#include <futex.h>
 
atomic_t keybuffer_futex = FUTEX_INITIALIZER;
 
/** Clear key buffer.
*/
void keybuffer_free(keybuffer_t *keybuffer)
{
futex_down(&keybuffer_futex);
keybuffer->head = 0;
keybuffer->tail = 0;
keybuffer->items = 0;
futex_up(&keybuffer_futex);
}
 
/** Key buffer initialization.
*
*/
void keybuffer_init(keybuffer_t *keybuffer)
{
keybuffer_free(keybuffer);
}
 
/** Get free space in buffer.
* This function is useful for processing some scancodes that are translated
* to more than one character.
* @return empty buffer space
*/
int keybuffer_available(keybuffer_t *keybuffer)
{
return KEYBUFFER_SIZE - keybuffer->items;
}
 
/**
* @return nonzero, if buffer is not empty.
*/
int keybuffer_empty(keybuffer_t *keybuffer)
{
return (keybuffer->items == 0);
}
 
/** Push key event to key buffer.
*
* If the buffer is full, the event is ignored.
*
* @param keybuffer The keybuffer.
* @param ev The event to push.
*/
void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev)
{
futex_down(&keybuffer_futex);
if (keybuffer->items < KEYBUFFER_SIZE) {
keybuffer->fifo[keybuffer->tail] = *ev;
keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE;
keybuffer->items++;
}
futex_up(&keybuffer_futex);
}
 
/** Pop event from buffer.
*
* @param edst Pointer to where the event should be saved.
* @return Zero on empty buffer, nonzero otherwise.
*/
int keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst)
{
futex_down(&keybuffer_futex);
if (keybuffer->items > 0) {
keybuffer->items--;
*edst = (keybuffer->fifo[keybuffer->head]) ;
keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE;
futex_up(&keybuffer_futex);
return 1;
}
futex_up(&keybuffer_futex);
return 0;
}
 
/**
* @}
*/
/branches/network/uspace/srv/kbd/Makefile
34,7 → 34,7
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -Iinclude
CFLAGS += -Iinclude -I../libadt/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
46,7 → 46,7
generic/kbd.c \
genarch/gsp.c \
genarch/stroke.c \
generic/keybuffer.c
generic/key_buffer.c
 
ARCH_SOURCES =
GENARCH_SOURCES = \
112,15 → 112,8
 
ifeq ($(MACHINE), bgxemul)
GENARCH_SOURCES += \
port/gxemul.c
ifeq ($(CONFIG_FB), y)
GENARCH_SOURCES += \
ctl/gxe_fb.c
else
GENARCH_SOURCES += \
ctl/stty.c
endif
port/gxemul.c \
ctl/stty.c
endif
 
ifeq ($(UARCH), ppc32)
167,7 → 160,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/kbd/layout/us_qwerty.c
32,12 → 32,12
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
layout_op_t us_qwerty_op = {
layout_reset,
203,7 → 203,7
{
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
wchar_t c;
 
/branches/network/uspace/srv/kbd/layout/cz.c
27,23 → 27,23
*/
 
/** @addtogroup kbd
* @brief US QWERTY leyout.
* @brief US QWERTY leyout.
* @{
*/
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <bool.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
enum m_state {
ms_start,
ms_hacek,
ms_carka
ms_carka
};
 
static enum m_state mstate;
272,7 → 272,7
return map[key];
}
 
static wchar_t parse_ms_hacek(console_event_t *ev)
static wchar_t parse_ms_hacek(kbd_event_t *ev)
{
wchar_t c;
 
290,7 → 290,7
return c;
}
 
static wchar_t parse_ms_carka(console_event_t *ev)
static wchar_t parse_ms_carka(kbd_event_t *ev)
{
wchar_t c;
 
308,7 → 308,7
return c;
}
 
static wchar_t parse_ms_start(console_event_t *ev)
static wchar_t parse_ms_start(kbd_event_t *ev)
{
wchar_t c;
 
383,24 → 383,21
mstate = ms_start;
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
if (ev->type != KEY_PRESS)
return 0;
if (ev->type != KE_PRESS)
return '\0';
 
if (key_is_mod(ev->key))
return 0;
return '\0';
 
switch (mstate) {
case ms_start:
return parse_ms_start(ev);
case ms_hacek:
return parse_ms_hacek(ev);
case ms_carka:
return parse_ms_carka(ev);
case ms_start: return parse_ms_start(ev);
case ms_hacek: return parse_ms_hacek(ev);
case ms_carka: return parse_ms_carka(ev);
}
}
 
/**
* @}
*/
*/
/branches/network/uspace/srv/kbd/layout/us_dvorak.c
32,12 → 32,12
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
layout_op_t us_dvorak_op = {
layout_reset,
209,7 → 209,7
{
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
wchar_t c;
 
/branches/network/uspace/srv/kbd/ctl/pc.c
32,12 → 32,12
*/
/**
* @file
* @brief PC keyboard controller driver.
* @brief PC keyboard controller driver.
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
 
188,7 → 188,7
 
void kbd_ctl_parse_scancode(int scancode)
{
console_ev_type_t type;
kbd_ev_type_t type;
unsigned int key;
int *map;
size_t map_length;
213,9 → 213,9
 
if (scancode & 0x80) {
scancode &= ~0x80;
type = KEY_RELEASE;
type = KE_RELEASE;
} else {
type = KEY_PRESS;
type = KE_PRESS;
}
 
if (scancode < 0 || scancode >= map_length)
/branches/network/uspace/srv/kbd/ctl/stty.c
36,7 → 36,8
*/
 
#include <kbd.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/network/uspace/srv/kbd/ctl/sun.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
 
#define KBD_KEY_RELEASE 0x80
52,7 → 52,7
 
void kbd_ctl_parse_scancode(int scancode)
{
console_ev_type_t type;
kbd_ev_type_t type;
unsigned int key;
 
if (scancode < 0 || scancode >= 0x100)
63,9 → 63,9
 
if (scancode & KBD_KEY_RELEASE) {
scancode &= ~KBD_KEY_RELEASE;
type = KEY_RELEASE;
type = KE_RELEASE;
} else {
type = KEY_PRESS;
type = KE_PRESS;
}
 
key = scanmap_simple[scancode];
/branches/network/uspace/srv/kbd/ctl/gxe_fb.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/network/uspace/srv/kbd/genarch/stroke.c
31,18 → 31,17
*/
/**
* @file
* @brief Stroke simulator.
* @brief Stroke simulator.
*
* When simulating a keyboard using a serial TTY we need to convert the
* recognized strokes (such as Shift-A) to sequences of key presses and
* releases (such as 'press Shift, press A, release A, release Shift').
*
*/
 
#include <stroke.h>
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
 
/** Correspondence between modifers and the modifier keycodes. */
static unsigned int mods_keys[][2] = {
59,7 → 58,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
kbd_push_ev(KE_PRESS, mods_keys[i][1]);
}
++i;
}
66,8 → 65,8
 
/* Simulate key press and release. */
if (key != 0) {
kbd_push_ev(KEY_PRESS, key);
kbd_push_ev(KEY_RELEASE, key);
kbd_push_ev(KE_PRESS, key);
kbd_push_ev(KE_RELEASE, key);
}
 
/* Simulate modifier releases. */
74,7 → 73,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
kbd_push_ev(KE_RELEASE, mods_keys[i][1]);
}
++i;
}
82,4 → 81,4
 
/**
* @}
*/
*/
/branches/network/uspace/srv/kbd/genarch/gsp.c
49,7 → 49,7
*/
 
#include <gsp.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <stdlib.h>
#include <stdio.h>
 
/branches/network/uspace/srv/console/gfx/cons_kernel.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/anim_1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/anim_2.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/anim_3.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/cons_has_data.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/anim_4.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/cons_selected.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/nameic.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/helenos.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/gfx/cons_idle.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/console.c
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
36,71 → 36,96
#include <fb.h>
#include <ipc/ipc.h>
#include <kbd.h>
#include <io/keycode.h>
#include <kbd/keycode.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <errno.h>
#include <keybuffer.h>
#include <key_buffer.h>
#include <ipc/console.h>
#include <unistd.h>
#include <async.h>
#include <adt/fifo.h>
#include <libadt/fifo.h>
#include <screenbuffer.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <sysinfo.h>
#include <event.h>
#include <devmap.h>
#include <fibril_sync.h>
 
#include "console.h"
#include "gcons.h"
#include "screenbuffer.h"
 
#define NAME "console"
#define MAX_KEYREQUESTS_BUFFERED 32
 
#define MAX_DEVICE_NAME 32
#define NAME "console"
 
/** Phone to the keyboard driver. */
static int kbd_phone;
/** Index of currently used virtual console.
*/
int active_console = 0;
int prev_console = 0;
 
/** Information about framebuffer */
struct {
int phone; /**< Framebuffer phone */
ipcarg_t cols; /**< Framebuffer columns */
ipcarg_t rows; /**< Framebuffer rows */
int phone; /**< Framebuffer phone */
ipcarg_t rows; /**< Framebuffer rows */
ipcarg_t cols; /**< Framebuffer columns */
} fb_info;
 
typedef struct {
size_t index; /**< Console index */
size_t refcount; /**< Connection reference count */
dev_handle_t dev_handle; /**< Device handle */
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
screenbuffer_t scr; /**< Screenbuffer for saving screen
contents and related settings. */
} console_t;
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
/** Buffer for unsatisfied request for keys. */
FIFO_CREATE_STATIC(keyrequests, ipc_callid_t,
MAX_KEYREQUESTS_BUFFERED);
int keyrequest_counter; /**< Number of requests in buffer. */
int client_phone; /**< Phone to connected client. */
int used; /**< 1 if this virtual console is
* connected to some client.*/
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen
* contents and related settings. */
} connection_t;
 
/** Array of data for virtual consoles */
static console_t consoles[CONSOLE_COUNT];
static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual
* consoles */
static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared
* with framebufer used for
* faster virtual console
* switching */
 
static console_t *active_console = &consoles[0];
static console_t *prev_console = &consoles[0];
static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
 
/** Pointer to memory shared with framebufer used for
faster virtual console switching */
static keyfield_t *interbuffer = NULL;
 
/** Information on row-span yet unsent to FB driver. */
struct {
size_t col; /**< Leftmost column of the span. */
size_t row; /**< Row where the span lies. */
size_t cnt; /**< Width of the span. */
int row; /**< Row where the span lies. */
int col; /**< Leftmost column of the span. */
int n; /**< Width of the span. */
} fb_pending;
 
static FIBRIL_MUTEX_INITIALIZE(input_mutex);
static FIBRIL_CONDVAR_INITIALIZE(input_cv);
/** Size of cwrite_buf. */
#define CWRITE_BUF_SIZE 256
 
/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
static char cwrite_buf[CWRITE_BUF_SIZE];
 
static void fb_putchar(wchar_t c, int row, int col);
 
 
/** Find unused virtual console.
*
*/
static int find_free_connection(void)
{
int i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (!connections[i].used)
return i;
}
return -1;
}
 
static void clrscr(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void curs_visibility(bool visible)
{
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
111,16 → 136,11
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
}
 
static void curs_goto(size_t x, size_t y)
static void curs_goto(int row, int col)
{
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
}
 
static void screen_clear(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void screen_yield(void)
{
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
131,19 → 151,9
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
}
 
static void kbd_yield(void)
{
ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
}
 
static void kbd_reclaim(void)
{
ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
}
 
static void set_style(int style)
{
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
}
 
static void set_color(int fgcolor, int bgcolor, int flags)
162,10 → 172,12
case at_style:
set_style(attrs->a.s.style);
break;
 
case at_idx:
set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
attrs->a.i.flags);
break;
 
case at_rgb:
set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
break;
173,31 → 185,57
}
 
/** 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)
static void fb_update_area(connection_t *conn, int x, int y, int w, int h)
{
int i, j;
int rc;
attrs_t *attrs;
keyfield_t *field;
 
if (interbuffer) {
ipcarg_t x;
ipcarg_t y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
interbuffer[y * width + x] =
*get_field_at(&cons->scr, x0 + x, y0 + y);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
interbuffer[i + j * w] =
*get_field_at(&conn->screenbuffer,
x + i, y + j);
}
}
async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
x0, y0, width, height);
 
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
x, y, w, h);
} else {
rc = ENOTSUP;
}
 
if (rc != 0) {
/*
attrs = &conn->screenbuffer.attrs;
 
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
field = get_field_at(&conn->screenbuffer,
x + i, y + j);
if (!attrs_same(*attrs, field->attrs))
set_attrs(&field->attrs);
attrs = &field->attrs;
 
fb_putchar(field->character, y + j, x + i);
}
}*/
}
}
 
/** Flush pending cells to FB. */
static void fb_pending_flush(void)
{
if (fb_pending.cnt > 0) {
fb_update_area(active_console, fb_pending.col,
fb_pending.row, fb_pending.cnt, 1);
fb_pending.cnt = 0;
screenbuffer_t *scr;
 
scr = &(connections[active_console].screenbuffer);
 
if (fb_pending.n > 0) {
fb_update_area(&connections[active_console], fb_pending.col,
fb_pending.row, fb_pending.n, 1);
fb_pending.n = 0;
}
}
 
205,162 → 243,167
*
* This adds the cell to the pending rowspan if possible. Otherwise
* the old span is flushed first.
*
*/
static void cell_mark_changed(size_t col, size_t row)
static void cell_mark_changed(int row, int col)
{
if (fb_pending.cnt != 0) {
if ((col != fb_pending.col + fb_pending.cnt)
|| (row != fb_pending.row)) {
if (fb_pending.n != 0) {
if (row != fb_pending.row ||
col != fb_pending.col + fb_pending.n) {
fb_pending_flush();
}
}
if (fb_pending.cnt == 0) {
 
if (fb_pending.n == 0) {
fb_pending.row = row;
fb_pending.col = col;
fb_pending.row = row;
}
fb_pending.cnt++;
 
++fb_pending.n;
}
 
 
/** Print a character to the active VC with buffering. */
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
static void fb_putchar(wchar_t c, int row, int col)
{
async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
}
 
/** Process a character from the client (TTY emulation). */
static void write_char(console_t *cons, wchar_t ch)
static void write_char(int console, wchar_t ch)
{
bool flush_cursor = false;
screenbuffer_t *scr = &(connections[console].screenbuffer);
 
switch (ch) {
case '\n':
fb_pending_flush();
flush_cursor = true;
cons->scr.position_y++;
cons->scr.position_x = 0;
scr->position_y++;
scr->position_x = 0;
break;
case '\r':
break;
case '\t':
cons->scr.position_x += 8;
cons->scr.position_x -= cons->scr.position_x % 8;
scr->position_x += 8;
scr->position_x -= scr->position_x % 8;
break;
case '\b':
if (cons->scr.position_x == 0)
if (scr->position_x == 0)
break;
cons->scr.position_x--;
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(&cons->scr, ' ');
scr->position_x--;
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
screenbuffer_putchar(scr, ' ');
break;
default:
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(&cons->scr, ch);
cons->scr.position_x++;
default:
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
 
screenbuffer_putchar(scr, ch);
scr->position_x++;
}
if (cons->scr.position_x >= cons->scr.size_x) {
 
if (scr->position_x >= scr->size_x) {
flush_cursor = true;
cons->scr.position_y++;
scr->position_y++;
}
if (cons->scr.position_y >= cons->scr.size_y) {
if (scr->position_y >= scr->size_y) {
fb_pending_flush();
cons->scr.position_y = cons->scr.size_y - 1;
screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
if (cons == active_console)
scr->position_y = scr->size_y - 1;
screenbuffer_clear_line(scr, scr->top_line);
scr->top_line = (scr->top_line + 1) % scr->size_y;
if (console == active_console)
async_msg_1(fb_info.phone, FB_SCROLL, 1);
}
 
if (cons == active_console && flush_cursor)
curs_goto(cons->scr.position_x, cons->scr.position_y);
cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
scr->position_x = scr->position_x % scr->size_x;
 
if (console == active_console && flush_cursor)
curs_goto(scr->position_y, scr->position_x);
}
 
/** Switch to new console */
static void change_console(console_t *cons)
static void change_console(int newcons)
{
if (cons == active_console)
connection_t *conn;
int i, j, rc;
keyfield_t *field;
attrs_t *attrs;
if (newcons == active_console)
return;
 
fb_pending_flush();
if (cons == kernel_console) {
 
if (newcons == KERNEL_CONSOLE) {
async_serialize_start();
curs_hide_sync();
gcons_in_kernel();
screen_yield();
kbd_yield();
async_serialize_end();
 
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
prev_console = active_console;
active_console = kernel_console;
active_console = KERNEL_CONSOLE;
} else
cons = active_console;
newcons = active_console;
}
if (cons != kernel_console) {
size_t x;
size_t y;
int rc = 0;
if (newcons != KERNEL_CONSOLE) {
async_serialize_start();
if (active_console == kernel_console) {
if (active_console == KERNEL_CONSOLE) {
screen_reclaim();
kbd_reclaim();
gcons_redraw_console();
}
active_console = cons;
gcons_change_console(cons->index);
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
set_attrs(&cons->scr.attrs);
set_attrs(&conn->screenbuffer.attrs);
curs_visibility(false);
if (interbuffer) {
for (y = 0; y < cons->scr.size_y; y++) {
for (x = 0; x < cons->scr.size_x; x++) {
interbuffer[y * cons->scr.size_x + x] =
*get_field_at(&cons->scr, x, y);
for (j = 0; j < conn->screenbuffer.size_y; j++) {
for (i = 0; i < conn->screenbuffer.size_x; i++) {
unsigned int size_x;
size_x = conn->screenbuffer.size_x;
interbuffer[j * size_x + i] =
*get_field_at(&conn->screenbuffer, i, j);
}
}
/* This call can preempt, but we are already at the end */
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
0, 0, cons->scr.size_x,
cons->scr.size_y);
0, 0, conn->screenbuffer.size_x,
conn->screenbuffer.size_y);
}
if ((!interbuffer) || (rc != 0)) {
set_attrs(&cons->scr.attrs);
screen_clear();
set_attrs(&conn->screenbuffer.attrs);
clrscr();
attrs = &conn->screenbuffer.attrs;
for (y = 0; y < cons->scr.size_y; y++)
for (x = 0; x < cons->scr.size_x; x++) {
keyfield_t *field = get_field_at(&cons->scr, x, y);
if (!attrs_same(cons->scr.attrs, field->attrs))
for (j = 0; j < conn->screenbuffer.size_y; j++)
for (i = 0; i < conn->screenbuffer.size_x; i++) {
field = get_field_at(&conn->screenbuffer, i, j);
if (!attrs_same(*attrs, field->attrs))
set_attrs(&field->attrs);
cons->scr.attrs = field->attrs;
attrs = &field->attrs;
if ((field->character == ' ') &&
(attrs_same(field->attrs, cons->scr.attrs)))
(attrs_same(field->attrs,
conn->screenbuffer.attrs)))
continue;
fb_putchar(field->character, x, y);
 
fb_putchar(field->character, j, i);
}
}
curs_goto(cons->scr.position_x, cons->scr.position_y);
curs_visibility(cons->scr.is_cursor_visible);
curs_goto(conn->screenbuffer.position_y,
conn->screenbuffer.position_x);
curs_visibility(conn->screenbuffer.is_cursor_visible);
async_serialize_end();
}
369,19 → 412,31
/** Handler for keyboard */
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
{
/* Ignore parameters, the connection is already opened */
while (true) {
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
int retval;
console_event_t ev;
ipc_callid_t callid;
ipc_call_t call;
int retval;
kbd_event_t ev;
connection_t *conn;
int newcon;
/* Ignore parameters, the connection is alread opened */
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/* TODO: Handle hangup */
return;
case KBD_MS_LEFT:
newcon = gcons_mouse_btn(IPC_GET_ARG1(call));
if (newcon != -1)
change_console(newcon);
retval = 0;
break;
case KBD_MS_MOVE:
gcons_mouse_move(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
retval = 0;
break;
case KBD_EVENT:
/* Got event from keyboard driver. */
retval = 0;
390,19 → 445,30
ev.mods = IPC_GET_ARG3(call);
ev.c = IPC_GET_ARG4(call);
/* switch to another virtual console */
conn = &connections[active_console];
 
if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
if (ev.key == KC_F1 + KERNEL_CONSOLE)
change_console(kernel_console);
if (ev.key == KC_F12)
change_console(KERNEL_CONSOLE);
else
change_console(&consoles[ev.key - KC_F1]);
change_console(ev.key - KC_F1);
break;
}
fibril_mutex_lock(&input_mutex);
keybuffer_push(&active_console->keybuffer, &ev);
fibril_condvar_broadcast(&input_cv);
fibril_mutex_unlock(&input_mutex);
/* if client is awaiting key, send it */
if (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_4(fifo_pop(conn->keyrequests), EOK,
ev.type, ev.key, ev.mods, ev.c);
break;
}
 
keybuffer_push(&conn->keybuffer, &ev);
retval = 0;
 
break;
default:
retval = ENOENT;
411,132 → 477,62
}
}
 
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
/** Handle CONSOLE_WRITE call. */
static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
wchar_t ch;
size_t off;
 
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
(void) ipc_data_write_finalize(callid, buf, size);
async_serialize_start();
size_t off = 0;
while (off < size) {
wchar_t ch = str_decode(buf, &off, size);
write_char(cons, ch);
}
async_serialize_end();
gcons_notify_char(cons->index);
ipc_answer_1(rid, EOK, size);
free(buf);
}
 
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
size_t pos = 0;
console_event_t ev;
fibril_mutex_lock(&input_mutex);
recheck:
while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
if (ev.type == KEY_PRESS) {
buf[pos] = ev.c;
pos++;
}
}
if (pos == size) {
(void) ipc_data_read_finalize(callid, buf, size);
ipc_answer_1(rid, EOK, size);
free(buf);
} else {
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
}
fibril_mutex_unlock(&input_mutex);
}
if (size > CWRITE_BUF_SIZE)
size = CWRITE_BUF_SIZE;
 
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
console_event_t ev;
(void) ipc_data_write_finalize(callid, cwrite_buf, size);
 
fibril_mutex_lock(&input_mutex);
recheck:
if (keybuffer_pop(&cons->keybuffer, &ev)) {
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
} else {
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
off = 0;
while (off < size) {
ch = str_decode(cwrite_buf, &off, size);
write_char(consnum, ch);
}
fibril_mutex_unlock(&input_mutex);
 
gcons_notify_char(consnum);
ipc_answer_1(rid, EOK, size);
}
 
/** Default thread for new connections */
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
console_t *cons = NULL;
ipc_callid_t callid;
ipc_call_t call;
int consnum;
ipcarg_t arg1, arg2, arg3, arg4;
connection_t *conn;
screenbuffer_t *scr;
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i == KERNEL_CONSOLE)
continue;
if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
cons = &consoles[i];
break;
}
}
if (cons == NULL) {
ipc_answer_0(iid, ENOENT);
if ((consnum = find_free_connection()) == -1) {
ipc_answer_0(iid, ELIMIT);
return;
}
conn = &connections[consnum];
conn->used = 1;
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t arg1;
ipcarg_t arg2;
ipcarg_t arg3;
async_serialize_start();
if (cons->refcount == 0)
gcons_notify_connect(cons->index);
gcons_notify_connect(consnum);
conn->client_phone = IPC_GET_ARG5(*icall);
screenbuffer_clear(&conn->screenbuffer);
if (consnum == active_console)
clrscr();
cons->refcount++;
/* Accept the connection */
ipc_answer_0(iid, EOK);
while (true) {
while (1) {
async_serialize_end();
callid = async_get_call(&call);
async_serialize_start();
544,55 → 540,62
arg1 = 0;
arg2 = 0;
arg3 = 0;
arg4 = 0;
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cons->refcount--;
if (cons->refcount == 0)
gcons_notify_disconnect(cons->index);
gcons_notify_disconnect(consnum);
/* Answer all pending requests */
while (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_0(fifo_pop(conn->keyrequests),
ENOENT);
break;
}
conn->used = 0;
return;
case VFS_READ:
async_serialize_end();
cons_read(cons, callid, &call);
async_serialize_start();
case CONSOLE_PUTCHAR:
write_char(consnum, IPC_GET_ARG1(call));
gcons_notify_char(consnum);
break;
case CONSOLE_WRITE:
cons_write(consnum, callid, &call);
continue;
case VFS_WRITE:
async_serialize_end();
cons_write(cons, callid, &call);
async_serialize_start();
continue;
case VFS_SYNC:
fb_pending_flush();
if (cons == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
curs_goto(cons->scr.position_x, cons->scr.position_y);
}
break;
case CONSOLE_CLEAR:
/* Send message to fb */
if (cons == active_console)
async_msg_0(fb_info.phone, FB_CLEAR);
if (consnum == active_console) {
async_msg_0(fb_info.phone, FB_CLEAR);
}
screenbuffer_clear(&cons->scr);
screenbuffer_clear(&conn->screenbuffer);
break;
case CONSOLE_GOTO:
screenbuffer_goto(&cons->scr,
IPC_GET_ARG1(call), IPC_GET_ARG2(call));
if (cons == active_console)
screenbuffer_goto(&conn->screenbuffer,
IPC_GET_ARG2(call), IPC_GET_ARG1(call));
if (consnum == active_console)
curs_goto(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
break;
case CONSOLE_GET_SIZE:
arg1 = fb_info.cols;
arg2 = fb_info.rows;
case CONSOLE_GETSIZE:
arg1 = fb_info.rows;
arg2 = fb_info.cols;
break;
case CONSOLE_FLUSH:
fb_pending_flush();
if (consnum == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
 
scr = &(connections[consnum].screenbuffer);
curs_goto(scr->position_y, scr->position_x);
}
break;
case CONSOLE_SET_STYLE:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
screenbuffer_set_style(&cons->scr, arg1);
if (cons == active_console)
screenbuffer_set_style(&conn->screenbuffer, arg1);
if (consnum == active_console)
set_style(arg1);
break;
case CONSOLE_SET_COLOR:
600,8 → 603,9
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
arg3 = IPC_GET_ARG3(call);
screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
if (cons == active_console)
screenbuffer_set_color(&conn->screenbuffer, arg1,
arg2, arg3);
if (consnum == active_console)
set_color(arg1, arg2, arg3);
break;
case CONSOLE_SET_RGB_COLOR:
608,27 → 612,46
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
if (cons == active_console)
screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
arg2);
if (consnum == active_console)
set_rgb_color(arg1, arg2);
break;
case CONSOLE_CURSOR_VISIBILITY:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
cons->scr.is_cursor_visible = arg1;
if (cons == active_console)
conn->screenbuffer.is_cursor_visible = arg1;
if (consnum == active_console)
curs_visibility(arg1);
break;
case CONSOLE_GET_EVENT:
async_serialize_end();
cons_get_event(cons, callid, &call);
async_serialize_start();
continue;
case CONSOLE_GETKEY:
if (keybuffer_empty(&conn->keybuffer)) {
/* buffer is empty -> store request */
if (conn->keyrequest_counter <
MAX_KEYREQUESTS_BUFFERED) {
fifo_push(conn->keyrequests, callid);
conn->keyrequest_counter++;
} else {
/*
* No key available and too many
* requests => fail.
*/
ipc_answer_0(callid, ELIMIT);
}
continue;
}
kbd_event_t ev;
keybuffer_pop(&conn->keybuffer, &ev);
arg1 = ev.type;
arg2 = ev.key;
arg3 = ev.mods;
arg4 = ev.c;
break;
case CONSOLE_KCON_ENABLE:
change_console(kernel_console);
change_console(KERNEL_CONSOLE);
break;
}
ipc_answer_3(callid, EOK, arg1, arg2, arg3);
ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4);
}
}
 
637,23 → 660,31
change_console(prev_console);
}
 
static bool console_init(void)
int main(int argc, char *argv[])
{
printf(NAME ": HelenOS Console service\n");
ipcarg_t phonehash;
int kbd_phone;
size_t ib_size;
int i;
async_set_client_connection(client_connection);
/* Connect to keyboard driver */
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
if (kbd_phone < 0) {
printf(NAME ": Failed to connect to keyboard service\n");
return false;
return -1;
}
ipcarg_t phonehash;
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
printf(NAME ": Failed to create callback from keyboard service\n");
return false;
return -1;
}
async_new_connection(phonehash, 0, NULL, keyboard_events);
 
/* Connect to framebuffer driver */
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
if (fb_info.phone < 0) {
661,28 → 692,48
return -1;
}
/* Register driver */
int rc = devmap_driver_register(NAME, client_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver (%d)\n", rc);
return false;
}
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize gcons */
gcons_init(fb_info.phone);
/* Synchronize, the gcons could put something in queue */
/* Synchronize, the gcons can have 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_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
&fb_info.cols);
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
clrscr();
/* Init virtual consoles */
for (i = 0; i < CONSOLE_COUNT; i++) {
connections[i].used = 0;
keybuffer_init(&connections[i].keybuffer);
connections[i].keyrequests.head = 0;
connections[i].keyrequests.tail = 0;
connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
connections[i].keyrequest_counter = 0;
if (screenbuffer_init(&connections[i].screenbuffer,
fb_info.cols, fb_info.rows) == NULL) {
/* FIXME: handle error */
return -1;
}
}
connections[KERNEL_CONSOLE].used = 1;
 
/* Set up shared memory buffer. */
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
interbuffer = as_get_mappable_page(ib_size);
 
fb_pending.n = 0;
 
if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
interbuffer = NULL;
}
 
if (interbuffer) {
if (ipc_share_out_start(fb_info.phone, interbuffer,
AS_AREA_READ) != EOK) {
691,62 → 742,22
}
}
fb_pending.cnt = 0;
curs_goto(0, 0);
curs_visibility(
connections[active_console].screenbuffer.is_cursor_visible);
/* Inititalize consoles */
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i != KERNEL_CONSOLE) {
if (screenbuffer_init(&consoles[i].scr,
fb_info.cols, fb_info.rows) == NULL) {
printf(NAME ": Unable to allocate screen buffer %u\n", i);
return false;
}
screenbuffer_clear(&consoles[i].scr);
keybuffer_init(&consoles[i].keybuffer);
consoles[i].index = i;
consoles[i].refcount = 0;
char vc[MAX_DEVICE_NAME];
snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s\n", vc);
return false;
}
}
}
/* Register at NS */
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
return -1;
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize the screen */
async_serialize_start();
gcons_redraw_console();
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
screen_clear();
curs_goto(0, 0);
curs_visibility(active_console->scr.is_cursor_visible);
async_serialize_end();
/* Receive kernel notifications */
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
printf(NAME ": Error registering kconsole notifications\n");
async_set_interrupt_received(interrupt_received);
return true;
}
 
int main(int argc, char *argv[])
{
printf(NAME ": HelenOS Console service\n");
if (!console_init())
return -1;
printf(NAME ": Accepting connections\n");
// FIXME: avoid connectiong to itself, keep using klog
// printf(NAME ": Accepting connections\n");
async_manager();
return 0;
/branches/network/uspace/srv/console/screenbuffer.c
27,50 → 27,44
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#include <screenbuffer.h>
#include <io/style.h>
#include <console/style.h>
#include <malloc.h>
#include <unistd.h>
 
/** Store one character to screenbuffer.
/** Store one character to screenbuffer. Its position is determined by
* scr->position_x and scr->position_y.
*
* Its position is determined by scr->position_x
* and scr->position_y.
*
* @param scr Screenbuffer
* @param c Stored character
*
* @param scr screenbuffer
* @param c stored character
*/
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t ch)
{
keyfield_t *field =
get_field_at(scr, scr->position_x, scr->position_y);
keyfield_t *field;
 
field = get_field_at(scr, scr->position_x, scr->position_y);
 
field->character = ch;
field->attrs = scr->attrs;
}
 
/** Initilize screenbuffer.
*
* Allocate space for screen content in accordance to given size.
*
* @param scr Initialized screenbuffer
* @param size_x Width in characters
* @param size_y Height in characters
*
* @return Pointer to screenbuffer (same as scr parameter) or NULL
*
/** Initilize screenbuffer. Allocate space for screen content in accordance to given size.
* @param scr initialized screenbuffer
* @param size_x width in characters
* @param size_y height in characters
* @return pointer to screenbuffer (same as scr parameter) or NULL
*/
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y)
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y)
{
scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y);
if (!scr->buffer)
if (!scr->buffer) {
return NULL;
}
scr->size_x = size_x;
scr->size_y = size_y;
83,63 → 77,56
return scr;
}
 
/** Clear screenbuffer.
*
* @param scr Screenbuffer
*
/** Clear screenbuffer.
* @param scr screenbuffer
*/
void screenbuffer_clear(screenbuffer_t *scr)
{
size_t i;
unsigned int i;
for (i = 0; i < (scr->size_x * scr->size_y); i++) {
scr->buffer[i].character = ' ';
scr->buffer[i].attrs = scr->attrs;
}
 
scr->top_line = 0;
scr->position_y = 0;
scr->position_x = 0;
scr->position_y = 0;
}
 
/** Clear one buffer line.
*
* @param scr
* @param line One buffer line (not a screen line!)
*
*/
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line)
{
size_t x;
unsigned int i;
for (x = 0; x < scr->size_x; x++) {
scr->buffer[x + line * scr->size_x].character = ' ';
scr->buffer[x + line * scr->size_x].attrs = scr->attrs;
for (i = 0; i < scr->size_x; i++) {
scr->buffer[i + line * scr->size_x].character = ' ';
scr->buffer[i + line * scr->size_x].attrs = scr->attrs;
}
}
 
/** Copy content buffer from screenbuffer to given memory.
*
* @param scr Source screenbuffer
* @param dest Destination
*
* @param scr source screenbuffer
* @param dest destination
*/
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
{
size_t i;
unsigned int i;
for (i = 0; i < (scr->size_x * scr->size_y); i++)
for (i = 0; i < scr->size_x * scr->size_y; i++) {
dest[i] = scr->buffer[i];
}
}
 
/** Set new cursor position in screenbuffer.
*
* @param scr
* @param x
* @param y
*
*/
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y)
{
scr->position_x = x % scr->size_x;
scr->position_y = y % scr->size_y;
146,13 → 133,11
}
 
/** Set new style.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style)
void screenbuffer_set_style(screenbuffer_t *scr, int style)
{
scr->attrs.t = at_style;
scr->attrs.a.s.style = style;
159,13 → 144,11
}
 
/** Set new color.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags)
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color, unsigned int flags)
{
scr->attrs.t = at_idx;
scr->attrs.a.i.fg_color = fg_color;
174,13 → 157,11
}
 
/** Set new RGB color.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color)
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color)
{
scr->attrs.t = at_rgb;
scr->attrs.a.r.fg_color = fg_color;
187,5 → 168,6
scr->attrs.a.r.bg_color = bg_color;
}
 
/** @}
*/
/branches/network/uspace/srv/console/screenbuffer.h
27,20 → 27,19
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#ifndef SCREENBUFFER_H__
#define SCREENBUFFER_H__
#ifndef __SCREENBUFFER_H__
#define __SCREENBUFFER_H__
 
#include <stdint.h>
#include <sys/types.h>
#include <bool.h>
 
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
 
typedef struct {
uint8_t style;
53,8 → 52,8
} attr_idx_t;
 
typedef struct {
uint32_t bg_color; /**< background color */
uint32_t fg_color; /**< foreground color */
uint32_t bg_color; /**< background color */
uint32_t fg_color; /**< foreground color */
} attr_rgb_t;
 
typedef struct {
67,91 → 66,73
attr_style_t s;
attr_idx_t i;
attr_rgb_t r;
} a;
} a;
} attrs_t;
 
/** One field on screen. It contain one character and its attributes. */
typedef struct {
wchar_t character; /**< Character itself */
attrs_t attrs; /**< Character attributes */
wchar_t character; /**< Character itself */
attrs_t attrs; /**< Character`s attributes */
} keyfield_t;
 
/** Structure for buffering state of one virtual console.
*/
typedef struct {
keyfield_t *buffer; /**< Screen content - characters and
their attributes (used as a circular buffer) */
size_t size_x; /**< Number of columns */
size_t size_y; /**< Number of rows */
/** Coordinates of last printed character for determining cursor position */
size_t position_x;
size_t position_y;
attrs_t attrs; /**< Current attributes. */
size_t top_line; /**< Points to buffer[][] line that will
be printed at screen as the first line */
bool is_cursor_visible; /**< Cursor state - default is visible */
keyfield_t *buffer; /**< Screen content - characters and their attributes. Used as a circular buffer. */
unsigned int size_x, size_y; /**< Number of columns and rows */
unsigned int position_x, position_y; /**< Coordinates of last printed character for determining cursor position */
attrs_t attrs; /**< Current attributes. */
unsigned int top_line; /**< Points to buffer[][] line that will be printed at screen as the first line */
unsigned char is_cursor_visible; /**< Cursor state - default is visible */
} screenbuffer_t;
 
/** Returns keyfield for position on screen
*
* Screenbuffer->buffer is cyclic buffer so we
* must couted in index of the topmost line.
*
* @param scr Screenbuffer
* @param x Position on screen
* @param y Position on screen
*
* @return Keyfield structure with character and its attributes on x, y
*
/** Returns keyfield for position on screen. Screenbuffer->buffer is cyclic buffer so we must couted in index of the topmost line.
* @param scr screenbuffer
* @param x position on screen
* @param y position on screen
* @return keyfield structure with character and its attributes on x,y
*/
static inline keyfield_t *get_field_at(screenbuffer_t *scr, size_t x, size_t y)
static inline keyfield_t *get_field_at(screenbuffer_t *scr, unsigned int x, unsigned int y)
{
return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x;
}
 
/** Compares two sets of attributes.
*
* @param s1 First style
* @param s2 Second style
*
* @return Nonzero on equality
*
* @param s1 first style
* @param s2 second style
* @return nonzero on equality
*/
static inline int attrs_same(attrs_t a1, attrs_t a2)
{
if (a1.t != a2.t)
return 0;
if (a1.t != a2.t) return 0;
 
switch (a1.t) {
case at_style:
return (a1.a.s.style == a2.a.s.style);
case at_idx:
return (a1.a.i.fg_color == a2.a.i.fg_color)
&& (a1.a.i.bg_color == a2.a.i.bg_color)
&& (a1.a.i.flags == a2.a.i.flags);
case at_rgb:
return (a1.a.r.fg_color == a2.a.r.fg_color)
&& (a1.a.r.bg_color == a2.a.r.bg_color);
case at_style: return a1.a.s.style == a2.a.s.style;
case at_idx: return a1.a.i.fg_color == a2.a.i.fg_color &&
a1.a.i.bg_color == a2.a.i.bg_color &&
a1.a.i.flags == a2.a.i.flags;
case at_rgb: return a1.a.r.fg_color == a2.a.r.fg_color &&
a1.a.r.bg_color == a2.a.r.bg_color;
}
}
 
 
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t c);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y);
 
void screenbuffer_clear(screenbuffer_t *scr);
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line);
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line);
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest);
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y);
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style);
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color,
uint8_t bg_color, uint8_t attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color,
uint32_t bg_color);
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y);
void screenbuffer_set_style(screenbuffer_t *scr, int style);
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color, unsigned int attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color);
 
#endif
 
/** @}
*/
 
/branches/network/uspace/srv/console/console.h
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
35,10 → 35,11
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
 
#define CONSOLE_COUNT 12
#define KERNEL_CONSOLE 11
#define KERNEL_CONSOLE 11
 
#define CONSOLE_COUNT 12
 
#endif
 
/** @}
*/
/branches/network/uspace/srv/console/gcons.c
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
39,25 → 39,23
#include <sys/mman.h>
#include <string.h>
#include <align.h>
#include <bool.h>
 
#include "console.h"
#include "gcons.h"
 
#define CONSOLE_TOP 66
#define CONSOLE_MARGIN 6
#define CONSOLE_TOP 66
#define CONSOLE_MARGIN 6
 
#define STATUS_START 110
#define STATUS_TOP 8
#define STATUS_SPACE 4
#define STATUS_WIDTH 48
#define STATUS_HEIGHT 48
#define STATUS_START 110
#define STATUS_TOP 8
#define STATUS_SPACE 4
#define STATUS_WIDTH 48
#define STATUS_HEIGHT 48
 
#define MAIN_COLOR 0xffffff
#define MAIN_COLOR 0xffffff
 
static bool use_gcons = false;
static ipcarg_t xres;
static ipcarg_t yres;
static int use_gcons = 0;
static ipcarg_t xres,yres;
 
enum butstate {
CONS_DISCONNECTED = 0,
79,15 → 77,8
static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
static int animation = -1;
 
static size_t active_console = 0;
static int active_console = 0;
 
size_t mouse_x;
size_t mouse_y;
 
bool btn_pressed;
size_t btn_x;
size_t btn_y;
 
static void vp_switch(int vp)
{
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
94,7 → 85,8
}
 
/** Create view port */
static int vp_create(size_t x, size_t y, size_t width, size_t height)
static int vp_create(unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
{
return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
(width << 16) | height);
105,52 → 97,48
async_msg_0(fbphone, FB_CLEAR);
}
 
static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
static void set_rgb_color(int fgcolor, int bgcolor)
{
async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
}
 
/** Transparent putchar */
static void tran_putch(wchar_t ch, size_t col, size_t row)
static void tran_putch(char c, int row, int col)
{
async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
async_msg_3(fbphone, FB_PUTCHAR, c, row, col);
}
 
/** Redraw the button showing state of a given console */
static void redraw_state(size_t index)
static void redraw_state(int consnum)
{
vp_switch(cstatus_vp[index]);
enum butstate state = console_state[index];
char data[5];
int i;
enum butstate state = console_state[consnum];
 
vp_switch(cstatus_vp[consnum]);
if (ic_pixmaps[state] != -1)
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum],
ic_pixmaps[state]);
if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
&& (state != CONS_DISCONNECTED_SEL)) {
char data[5];
snprintf(data, 5, "%u", index + 1);
size_t i;
for (i = 0; data[i] != 0; i++)
tran_putch(data[i], 2 + i, 1);
}
 
if (state != CONS_DISCONNECTED && state != CONS_KERNEL &&
state != CONS_DISCONNECTED_SEL) {
snprintf(data, 5, "%d", consnum + 1);
for (i = 0; data[i]; i++)
tran_putch(data[i], 1, 2 + i);
}
}
 
/** Notification run on changing console (except kernel console) */
void gcons_change_console(size_t index)
void gcons_change_console(int consnum)
{
int i;
 
if (!use_gcons)
return;
 
if (active_console == KERNEL_CONSOLE) {
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
if (animation != -1)
async_msg_1(fbphone, FB_ANIM_START, animation);
} else {
158,74 → 146,71
console_state[active_console] = CONS_DISCONNECTED;
else
console_state[active_console] = CONS_IDLE;
redraw_state(active_console);
}
active_console = index;
if ((console_state[index] == CONS_DISCONNECTED)
|| (console_state[index] == CONS_DISCONNECTED_SEL))
console_state[index] = CONS_DISCONNECTED_SEL;
else
console_state[index] = CONS_SELECTED;
redraw_state(index);
active_console = consnum;
 
if (console_state[consnum] == CONS_DISCONNECTED) {
console_state[consnum] = CONS_DISCONNECTED_SEL;
redraw_state(consnum);
} else
console_state[consnum] = CONS_SELECTED;
redraw_state(consnum);
 
vp_switch(console_vp);
}
 
/** Notification function that gets called on new output to virtual console */
void gcons_notify_char(size_t index)
void gcons_notify_char(int consnum)
{
if (!use_gcons)
return;
if ((index == active_console)
|| (console_state[index] == CONS_HAS_DATA))
 
if (consnum == active_console ||
console_state[consnum] == CONS_HAS_DATA)
return;
console_state[index] = CONS_HAS_DATA;
 
console_state[consnum] = CONS_HAS_DATA;
 
if (active_console == KERNEL_CONSOLE)
return;
 
redraw_state(consnum);
redraw_state(index);
vp_switch(console_vp);
}
 
/** Notification function called on service disconnect from console */
void gcons_notify_disconnect(size_t index)
void gcons_notify_disconnect(int consnum)
{
if (!use_gcons)
return;
if (index == active_console)
console_state[index] = CONS_DISCONNECTED_SEL;
if (active_console == consnum)
console_state[consnum] = CONS_DISCONNECTED_SEL;
else
console_state[index] = CONS_DISCONNECTED;
console_state[consnum] = CONS_DISCONNECTED;
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(index);
redraw_state(consnum);
vp_switch(console_vp);
}
 
/** Notification function called on console connect */
void gcons_notify_connect(size_t index)
void gcons_notify_connect(int consnum)
{
if (!use_gcons)
return;
if (index == active_console)
console_state[index] = CONS_SELECTED;
if (active_console == consnum)
console_state[consnum] = CONS_SELECTED;
else
console_state[index] = CONS_IDLE;
console_state[consnum] = CONS_IDLE;
 
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(index);
 
redraw_state(consnum);
vp_switch(console_vp);
}
 
239,28 → 224,29
vp_switch(0);
}
 
/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */
static inline int limit(size_t a, size_t left, size_t right)
/** Return x, where left <= x <= right && |a-x|==min(|a-x|) is smallest */
static inline int limit(int a,int left, int right)
{
if (a < left)
a = left;
if (a >= right)
a = right - 1;
return a;
}
 
int mouse_x, mouse_y;
int btn_pressed, btn_x, btn_y;
 
/** Handle mouse move
*
* @param dx Delta X of mouse move
* @param dy Delta Y of mouse move
*/
void gcons_mouse_move(ssize_t dx, ssize_t dy)
void gcons_mouse_move(int dx, int dy)
{
mouse_x = limit(mouse_x + dx, 0, xres);
mouse_y = limit(mouse_y + dy, 0, yres);
 
async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
}
 
267,8 → 253,8
static int gcons_find_conbut(int x, int y)
{
int status_start = STATUS_START + (xres - 800) / 2;
if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
 
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT)
return -1;
if (x < status_start)
284,31 → 270,28
 
/** Handle mouse click
*
* @param state New state (true - pressed, false - depressed)
* @param state New state (1-pressed, 0-depressed)
*/
int gcons_mouse_btn(bool state)
int gcons_mouse_btn(int state)
{
int conbut;
 
if (state) {
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut != -1) {
btn_pressed = true;
btn_pressed = 1;
btn_x = mouse_x;
btn_y = mouse_y;
}
return -1;
}
if ((!state) && (!btn_pressed))
}
if (!state && !btn_pressed)
return -1;
btn_pressed = false;
btn_pressed = 0;
 
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut == gcons_find_conbut(btn_x, btn_y))
return conbut;
return -1;
}
 
324,40 → 307,35
{
char *shm;
int rc;
 
/* Create area */
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
MAP_ANONYMOUS, 0, 0);
if (shm == MAP_FAILED)
return;
 
memcpy(shm, logo, size);
/* Send area */
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
if (rc)
goto exit;
rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
if (rc)
goto drop;
/* Draw logo */
async_msg_2(fbphone, FB_DRAW_PPM, x, y);
drop:
/* Drop area */
async_msg_0(fbphone, FB_DROP_SHM);
exit:
exit:
/* Remove area */
munmap(shm, size);
}
 
extern char _binary_gfx_helenos_ppm_start[0];
extern int _binary_gfx_helenos_ppm_size;
extern char _binary_gfx_nameic_ppm_start[0];
extern int _binary_gfx_nameic_ppm_size;
extern char _binary_helenos_ppm_start[0];
extern int _binary_helenos_ppm_size;
extern char _binary_nameic_ppm_start[0];
extern int _binary_nameic_ppm_size;
 
/** Redraws console graphics */
void gcons_redraw_console(void)
370,14 → 348,13
vp_switch(0);
set_rgb_color(MAIN_COLOR, MAIN_COLOR);
clear();
draw_pixmap(_binary_gfx_helenos_ppm_start,
(size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
draw_pixmap(_binary_gfx_nameic_ppm_start,
(size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
draw_pixmap(_binary_helenos_ppm_start,
(size_t) &_binary_helenos_ppm_size, xres - 66, 2);
draw_pixmap(_binary_nameic_ppm_start,
(size_t) &_binary_nameic_ppm_size, 5, 17);
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
vp_switch(console_vp);
}
 
385,102 → 362,102
*
* @param data PPM data
* @param size PPM data size
*
* @return Pixmap identification
*
*/
static int make_pixmap(char *data, size_t size)
static int make_pixmap(char *data, int size)
{
char *shm;
int rc;
int pxid = -1;
 
/* Create area */
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
MAP_ANONYMOUS, 0, 0);
if (shm == MAP_FAILED)
return -1;
 
memcpy(shm, data, size);
/* Send area */
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
if (rc)
goto exit;
rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
if (rc)
goto drop;
 
/* Obtain pixmap */
rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
if (rc < 0)
goto drop;
pxid = rc;
drop:
/* Drop area */
async_msg_0(fbphone, FB_DROP_SHM);
exit:
exit:
/* Remove area */
munmap(shm, size);
 
return pxid;
}
 
extern char _binary_gfx_anim_1_ppm_start[0];
extern int _binary_gfx_anim_1_ppm_size;
extern char _binary_gfx_anim_2_ppm_start[0];
extern int _binary_gfx_anim_2_ppm_size;
extern char _binary_gfx_anim_3_ppm_start[0];
extern int _binary_gfx_anim_3_ppm_size;
extern char _binary_gfx_anim_4_ppm_start[0];
extern int _binary_gfx_anim_4_ppm_size;
extern char _binary_anim_1_ppm_start[0];
extern int _binary_anim_1_ppm_size;
extern char _binary_anim_2_ppm_start[0];
extern int _binary_anim_2_ppm_size;
extern char _binary_anim_3_ppm_start[0];
extern int _binary_anim_3_ppm_size;
extern char _binary_anim_4_ppm_start[0];
extern int _binary_anim_4_ppm_size;
 
static void make_anim(void)
{
int an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
int an;
int pm;
 
an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
if (an < 0)
return;
int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
(int) &_binary_gfx_anim_1_ppm_size);
 
pm = make_pixmap(_binary_anim_1_ppm_start,
(int) &_binary_anim_1_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
(int) &_binary_gfx_anim_2_ppm_size);
 
pm = make_pixmap(_binary_anim_2_ppm_start,
(int) &_binary_anim_2_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
(int) &_binary_gfx_anim_3_ppm_size);
 
pm = make_pixmap(_binary_anim_3_ppm_start,
(int) &_binary_anim_3_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
(int) &_binary_gfx_anim_4_ppm_size);
 
pm = make_pixmap(_binary_anim_4_ppm_start,
(int) &_binary_anim_4_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 
async_msg_1(fbphone, FB_ANIM_START, an);
 
animation = an;
}
 
extern char _binary_gfx_cons_selected_ppm_start[0];
extern int _binary_gfx_cons_selected_ppm_size;
extern char _binary_gfx_cons_idle_ppm_start[0];
extern int _binary_gfx_cons_idle_ppm_size;
extern char _binary_gfx_cons_has_data_ppm_start[0];
extern int _binary_gfx_cons_has_data_ppm_size;
extern char _binary_gfx_cons_kernel_ppm_start[0];
extern int _binary_gfx_cons_kernel_ppm_size;
extern char _binary_cons_selected_ppm_start[0];
extern int _binary_cons_selected_ppm_size;
extern char _binary_cons_idle_ppm_start[0];
extern int _binary_cons_idle_ppm_size;
extern char _binary_cons_has_data_ppm_start[0];
extern int _binary_cons_has_data_ppm_size;
extern char _binary_cons_kernel_ppm_start[0];
extern int _binary_cons_kernel_ppm_size;
 
/** Initialize nice graphical console environment */
void gcons_init(int phone)
{
int rc;
int i;
int status_start = STATUS_START;
fbphone = phone;
int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
if (rc)
return;
487,27 → 464,22
if ((xres < 800) || (yres < 600))
return;
/* Create console viewport */
/* create console viewport */
/* Align width & height to character size */
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
if (console_vp < 0)
return;
/* Create status buttons */
size_t status_start = STATUS_START + (xres - 800) / 2;
size_t i;
status_start += (xres - 800) / 2;
for (i = 0; i < CONSOLE_COUNT; i++) {
cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
STATUS_WIDTH, STATUS_HEIGHT);
if (cstatus_vp[i] < 0)
return;
vp_switch(cstatus_vp[i]);
set_rgb_color(0x202020, 0xffffff);
}
514,29 → 486,26
/* Initialize icons */
ic_pixmaps[CONS_SELECTED] =
make_pixmap(_binary_gfx_cons_selected_ppm_start,
(size_t) &_binary_gfx_cons_selected_ppm_size);
ic_pixmaps[CONS_IDLE] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(size_t) &_binary_gfx_cons_idle_ppm_size);
make_pixmap(_binary_cons_selected_ppm_start,
(int) &_binary_cons_selected_ppm_size);
ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
(int) &_binary_cons_idle_ppm_size);
ic_pixmaps[CONS_HAS_DATA] =
make_pixmap(_binary_gfx_cons_has_data_ppm_start,
(size_t) &_binary_gfx_cons_has_data_ppm_size);
make_pixmap(_binary_cons_has_data_ppm_start,
(int) &_binary_cons_has_data_ppm_size);
ic_pixmaps[CONS_DISCONNECTED] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(size_t) &_binary_gfx_cons_idle_ppm_size);
ic_pixmaps[CONS_KERNEL] =
make_pixmap(_binary_gfx_cons_kernel_ppm_start,
(size_t) &_binary_gfx_cons_kernel_ppm_size);
make_pixmap(_binary_cons_idle_ppm_start,
(int) &_binary_cons_idle_ppm_size);
ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
(int) &_binary_cons_kernel_ppm_size);
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
make_anim();
use_gcons = true;
use_gcons = 1;
console_state[0] = CONS_DISCONNECTED_SEL;
console_state[KERNEL_CONSOLE] = CONS_KERNEL;
vp_switch(console_vp);
gcons_redraw_console();
}
 
/** @}
/branches/network/uspace/srv/console/gcons.h
27,30 → 27,25
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#ifndef GCONS_H_
#define GCONS_H_
#ifndef _GCONS_H_
#define _GCONS_H_
 
#include <sys/types.h>
 
void gcons_init(int phone);
 
void gcons_redraw_console(void);
void gcons_change_console(size_t index);
void gcons_notify_char(size_t index);
void gcons_change_console(int consnum);
void gcons_notify_char(int consnum);
void gcons_in_kernel(void);
void gcons_notify_connect(int consnum);
void gcons_notify_disconnect(int consnum);
void gcons_mouse_move(int dx, int dy);
int gcons_mouse_btn(int state);
 
void gcons_notify_connect(size_t index);
void gcons_notify_disconnect(size_t index);
 
void gcons_mouse_move(ssize_t dx, ssize_t dy);
int gcons_mouse_btn(bool state);
 
#endif
 
/** @}
*/
/branches/network/uspace/srv/console/Makefile
42,29 → 42,23
#
 
OUTPUT = console
 
GENERIC_SOURCES = \
console.c \
screenbuffer.c \
../kbd/generic/keybuffer.c \
../kbd/generic/key_buffer.c \
gcons.c
 
IMAGES = \
gfx/helenos.ppm \
gfx/nameic.ppm \
gfx/cons_selected.ppm \
gfx/cons_idle.ppm \
gfx/cons_has_data.ppm \
gfx/cons_kernel.ppm \
gfx/anim_1.ppm \
gfx/anim_2.ppm \
gfx/anim_3.ppm \
gfx/anim_4.ppm
IMAGES = helenos.ppm nameic.ppm cons_selected.ppm cons_idle.ppm \
cons_has_data.ppm cons_kernel.ppm anim_1.ppm anim_2.ppm anim_3.ppm \
anim_4.ppm
 
ARCH_SOURCES =
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) \
$(addsuffix .o,$(basename $(IMAGES)))
$(addsuffix .o,$(basename $(IMAGES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
 
OBJECTS := $(GENERIC_OBJECTS)
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS)
 
.PHONY: all clean depend disasm
 
84,7 → 78,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/console/cons_kernel.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/anim_1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/anim_2.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/anim_3.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/anim_4.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/cons_has_data.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/cons_selected.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/cons_idle.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/nameic.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/console/helenos.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/network/uspace/srv/rd/rd.c
0,0 → 1,299
/*
* Copyright (c) 2007 Michal Konopa
* Copyright (c) 2007 Martin Jelen
* Copyright (c) 2007 Peter Majer
* Copyright (c) 2007 Jakub Jermar
* 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 rd
* @{
*/
 
/**
* @file rd.c
* @brief Initial RAM disk for HelenOS.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <futex.h>
#include <stdio.h>
#include <ipc/devmap.h>
#include "rd.h"
 
#define NAME "rd"
 
/** Pointer to the ramdisk's image. */
static void *rd_addr;
/** Size of the ramdisk. */
static size_t rd_size;
 
/**
* This futex protects the ramdisk's data.
* If we were to serve multiple requests (read + write or several writes)
* concurrently (i.e. from two or more threads), each read and write needs to be
* protected by this futex.
*/
atomic_t rd_futex = FUTEX_INITIALIZER;
 
/** Handle one connection to ramdisk.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
void *fs_va = NULL;
off_t offset;
size_t block_size;
size_t maxblock_size;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
/*
* Now we wait for the client to send us its communication as_area.
*/
int flags;
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
fs_va = as_get_mappable_page(maxblock_size);
if (fs_va) {
(void) ipc_share_out_finalize(callid, fs_va);
} else {
ipc_answer_0(callid, EHANGUP);
return;
}
} else {
/*
* The client doesn't speak the same protocol.
* At this point we can't handle protocol variations.
* Close the connection.
*/
ipc_answer_0(callid, EHANGUP);
return;
}
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/*
* The other side has hung up.
* Answer the message and exit the fibril.
*/
ipc_answer_0(callid, EOK);
return;
case RD_READ_BLOCK:
offset = IPC_GET_ARG1(call);
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Reading past the end of the device.
*/
retval = ELIMIT;
break;
}
futex_down(&rd_futex);
memcpy(fs_va, rd_addr + offset * block_size, block_size);
futex_up(&rd_futex);
retval = EOK;
break;
case RD_WRITE_BLOCK:
offset = IPC_GET_ARG1(call);
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Writing past the end of the device.
*/
retval = ELIMIT;
break;
}
futex_up(&rd_futex);
memcpy(rd_addr + offset * block_size, fs_va, block_size);
futex_down(&rd_futex);
retval = EOK;
break;
default:
/*
* The client doesn't speak the same protocol.
* Instead of closing the connection, we just ignore
* the call. This can be useful if the client uses a
* newer version of the protocol.
*/
retval = EINVAL;
break;
}
ipc_answer_0(callid, retval);
}
}
 
static int driver_register(char *name)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf(NAME ": Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(phone, (char *) name, str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return -1;
}
 
async_set_client_connection(rd_connection);
 
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
async_wait_for(req, &retval);
 
return phone;
}
 
static int device_register(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(driver_phone, (char *) name,
str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
if (EOK == retval) {
if (NULL != handle)
*handle = (int) IPC_GET_ARG1(answer);
}
return retval;
}
 
/** Prepare the ramdisk image for operation. */
static bool rd_init(void)
{
rd_size = sysinfo_value("rd.size");
void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
if (rd_size == 0) {
printf(NAME ": No RAM disk found\n");
return false;
}
rd_addr = as_get_mappable_page(rd_size);
int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
int retval = physmem_map(rd_ph_addr, rd_addr,
ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping RAM disk\n");
return false;
}
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size);
int driver_phone = driver_register(NAME);
if (driver_phone < 0) {
printf(NAME ": Unable to register driver\n");
return false;
}
int dev_handle;
if (EOK != device_register(driver_phone, "initrd", &dev_handle)) {
ipc_hangup(driver_phone);
printf(NAME ": Unable to register device\n");
return false;
}
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS RAM disk server\n");
if (!rd_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
/branches/network/uspace/srv/rd/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = rd
SOURCES = \
rd.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/network/uspace/srv/rd/rd.h
0,0 → 1,50
/*
* Copyright (c) 2007 Michal Konopa
* Copyright (c) 2007 Martin Jelen
* Copyright (c) 2007 Peter Majer
* Copyright (c) 2007 Jakub Jermar
* 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 rd
* @{
*/
 
/**
* @file rd.h
* @brief Initial RAM disk for HelenOS - header
*/
 
/* Basic constants. */
 
#ifndef RD_RD_H_
#define RD_RD_H_
 
#define RD_BASE 1024
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */
 
#endif
/branches/network/uspace/srv/loader/main.c
53,9 → 53,9
#include <ipc/services.h>
#include <ipc/loader.h>
#include <loader/pcb.h>
#include <console.h>
#include <errno.h>
#include <async.h>
#include <string.h>
#include <as.h>
 
#include <elf.h>
76,13 → 76,6
/** Buffer holding all arguments */
static char *arg_buf = NULL;
 
/** Number of preset files */
static int filc = 0;
/** Preset files vector */
static fdi_node_t **filv = NULL;
/** Buffer holding all preset files */
static fdi_node_t *fil_buf = NULL;
 
static elf_info_t prog_info;
static elf_info_t interp_info;
 
91,7 → 84,7
/** Used to limit number of connections to one. */
static bool connected;
 
static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
task_id_t task_id;
118,7 → 111,7
* @param rid
* @param request
*/
static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t len;
154,7 → 147,7
* @param rid
* @param request
*/
static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size, arg_size;
227,70 → 220,6
ipc_answer_0(rid, EOK);
}
 
/** Receive a call setting preset files of the program to execute.
*
* @param rid
* @param request
*/
static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size;
if (!ipc_data_write_receive(&callid, &buf_size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if ((buf_size % sizeof(fdi_node_t)) != 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if (fil_buf != NULL) {
free(fil_buf);
fil_buf = NULL;
}
if (filv != NULL) {
free(filv);
filv = NULL;
}
fil_buf = malloc(buf_size);
if (!fil_buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
ipc_data_write_finalize(callid, fil_buf, buf_size);
int count = buf_size / sizeof(fdi_node_t);
/* Allocate filvv */
filv = malloc((count + 1) * sizeof(fdi_node_t *));
if (filv == NULL) {
free(fil_buf);
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* Fill filv with argument pointers
*/
int i;
for (i = 0; i < count; i++)
filv[i] = &fil_buf[i];
filc = count;
filv[count] = NULL;
ipc_answer_0(rid, EOK);
}
 
/** Load the previously selected program.
*
* @param rid
297,12 → 226,12
* @param request
* @return 0 on success, !0 on error.
*/
static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
rc = elf_load_file(pathname, 0, &prog_info);
if (rc != EE_OK) {
if (rc < 0) {
DPRINTF("Failed to load executable '%s'.\n", pathname);
ipc_answer_0(rid, EINVAL);
return 1;
313,9 → 242,6
pcb.argc = argc;
pcb.argv = argv;
pcb.filc = filc;
pcb.filv = filv;
if (prog_info.interp == NULL) {
/* Statically linked program */
is_dyn_linked = false;
324,7 → 250,7
}
rc = elf_load_file(prog_info.interp, 0, &interp_info);
if (rc != EE_OK) {
if (rc < 0) {
DPRINTF("Failed to load interpreter '%s.'\n",
prog_info.interp);
ipc_answer_0(rid, EINVAL);
344,7 → 270,7
* @param request
* @return 0 on success, !0 on error.
*/
static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
{
const char *cp;
357,15 → 283,17
/* Dynamically linked program */
DPRINTF("Run ELF interpreter.\n");
DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
console_close();
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
} else {
/* Statically linked program */
console_close();
ipc_answer_0(rid, EOK);
elf_run(&prog_info, &pcb);
}
}
 
/* Not reached */
}
 
374,7 → 302,7
* Receive and carry out commands (of which the last one should be
* to execute the loaded program).
*/
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
402,22 → 330,19
case IPC_M_PHONE_HUNGUP:
exit(0);
case LOADER_GET_TASKID:
ldr_get_taskid(callid, &call);
loader_get_taskid(callid, &call);
continue;
case LOADER_SET_PATHNAME:
ldr_set_pathname(callid, &call);
loader_set_pathname(callid, &call);
continue;
case LOADER_SET_ARGS:
ldr_set_args(callid, &call);
loader_set_args(callid, &call);
continue;
case LOADER_SET_FILES:
ldr_set_files(callid, &call);
continue;
case LOADER_LOAD:
ldr_load(callid, &call);
loader_load(callid, &call);
continue;
case LOADER_RUN:
ldr_run(callid, &call);
loader_run(callid, &call);
/* Not reached */
default:
retval = ENOENT;
441,7 → 366,7
connected = false;
/* Set a handler of incomming connections. */
async_set_client_connection(ldr_connection);
async_set_client_connection(loader_connection);
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
/branches/network/uspace/srv/loader/elf_load.c
74,7 → 74,7
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
 
/** Read until the buffer is read in its entirety. */
static int my_read(int fd, void *buf, size_t len)
static int my_read(int fd, char *buf, size_t len)
{
int cnt = 0;
do {
331,26 → 331,21
int flags = 0;
uintptr_t bias;
uintptr_t base;
void *seg_ptr;
uintptr_t seg_addr;
size_t mem_sz;
int rc;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
entry->p_memsz);
bias = elf->bias;
 
seg_addr = entry->p_vaddr + bias;
seg_ptr = (void *) seg_addr;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", seg_addr,
entry->p_memsz);
 
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) !=
(seg_addr % entry->p_align)) {
(entry->p_vaddr % entry->p_align)) {
DPRINTF("Align check 1 failed offset%%align=%d, "
"vaddr%%align=%d\n",
entry->p_offset % entry->p_align,
seg_addr % entry->p_align
entry->p_vaddr % entry->p_align
);
return EE_INVALID;
}
369,7 → 364,7
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr,
DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias,
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
 
/*
384,7 → 379,7
}
 
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
base + bias, mem_sz, flags, (uintptr_t)a);
entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
 
/*
* Load segment data
404,7 → 399,7
uint8_t *dp;
 
left = entry->p_filesz;
dp = seg_ptr;
dp = (uint8_t *)(entry->p_vaddr + bias);
 
while (left > 0) {
now = 16384;
421,7 → 416,7
dp += now;
}
 
rc = as_area_change_flags(seg_ptr, flags);
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
if (rc != 0) {
DPRINTF("Failed to set memory area flags.\n");
return EE_MEMORY;
429,7 → 424,7
 
if (flags & AS_AREA_EXEC) {
/* Enforce SMC coherence for the segment */
if (smc_coherence(seg_ptr, entry->p_filesz))
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
return EE_MEMORY;
}
 
/branches/network/uspace/srv/loader/arch/ia32/ia32.s
46,4 → 46,4
# Save a tiny bit of stack space
pop %ebp
 
jmp *%eax
jmp %eax
/branches/network/uspace/srv/fb/serial_console.c
43,9 → 43,8
#include <ipc/fb.h>
#include <bool.h>
#include <errno.h>
#include <io/color.h>
#include <io/style.h>
#include <string.h>
#include <console/color.h>
#include <console/style.h>
 
#include "../console/screenbuffer.h"
#include "main.h"
129,9 → 128,9
 
}
 
void serial_goto(const unsigned int col, const unsigned int row)
void serial_goto(const unsigned int row, const unsigned int col)
{
if ((col > scr_width) || (row > scr_height))
if ((row > scr_height) || (col > scr_width))
return;
char control[MAX_CONTROL];
154,7 → 153,7
void serial_scroll(int i)
{
if (i > 0) {
serial_goto(0, scr_height - 1);
serial_goto(scr_height - 1, 0);
while (i--)
serial_puts("\033D");
} else if (i < 0) {
236,24 → 235,17
if (fgcolor < bgcolor)
serial_sgr(SGR_REVERSE_OFF);
else
serial_sgr(SGR_REVERSE);
serial_sgr(SGR_REVERSE);
}
 
static void serial_set_attrs(const attrs_t *a)
{
switch (a->t) {
case at_style:
serial_set_style(a->a.s.style);
break;
case at_rgb:
serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
break;
case at_idx:
serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
break;
default:
break;
case at_style: serial_set_style(a->a.s.style); break;
case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
case at_idx: serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags); break;
default: break;
}
}
 
273,13 → 265,13
keyfield_t *field;
attrs_t *a0, *a1;
 
serial_goto(x, y);
serial_goto(y, x);
a0 = &data[0].attrs;
serial_set_attrs(a0);
 
for (j = 0; j < h; j++) {
if (j > 0 && w != scr_width)
serial_goto(x, j);
serial_goto(y, x);
 
for (i = 0; i < w; i++) {
field = &data[j * w + i];
362,16 → 354,16
break;
}
draw_text_data(interbuf, col, row, w, h);
lastrow = row + h - 1;
lastcol = col + w;
lastrow = row + h - 1;
retval = 0;
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if ((lastcol != col) || (lastrow != row))
serial_goto(col, row);
serial_goto(row, col);
lastcol = col + 1;
lastrow = row;
serial_putchar(c);
378,15 → 370,15
retval = 0;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
serial_goto(col, row);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
serial_goto(row, col);
lastrow = row;
lastcol = col;
lastrow = row;
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
ipc_answer_2(callid, EOK, scr_height, scr_width);
continue;
case FB_CLEAR:
serial_clrscr();
424,7 → 416,7
break;
}
serial_scroll(i);
serial_goto(lastcol, lastrow);
serial_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
453,6 → 445,6
}
}
 
/**
/**
* @}
*/
/branches/network/uspace/srv/fb/fb.c
51,10 → 51,9
#include <ipc/services.h>
#include <kernel/errno.h>
#include <kernel/genarch/fb/visuals.h>
#include <io/color.h>
#include <io/style.h>
#include <console/color.h>
#include <console/style.h>
#include <async.h>
#include <fibril.h>
#include <bool.h>
 
#include "font-8x16.h"
376,8 → 375,8
*/
static void vport_redraw(viewport_t *vport)
{
unsigned int row;
unsigned int col;
unsigned int row;
for (row = 0; row < vport->rows; row++) {
for (col = 0; col < vport->cols; col++) {
432,8 → 431,8
*/
static void vport_scroll(viewport_t *vport, int lines)
{
unsigned int row;
unsigned int col;
unsigned int row;
unsigned int x;
unsigned int y;
uint32_t glyph;
450,8 → 449,7
for (row = 0; row < vport->rows; row++) {
x = vport->x;
for (col = 0; col < vport->cols; col++) {
if (((int) row + lines >= 0) &&
((int) row + lines < (int) vport->rows)) {
if ((row + lines >= 0) && (row + lines < vport->rows)) {
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
bbp = &vport->backbuf[BB_POS(vport, col, row)];
1040,8 → 1038,8
*
* @return false if the call was not handled byt this function, true otherwise
*
* Note: this function is not thread-safe, you would have
* to redefine static variables with fibril_local.
* Note: this function is not threads safe, you would have
* to redefine static variables with __thread
*
*/
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1566,7 → 1564,7
unsigned int i;
int scroll;
wchar_t ch;
unsigned int col, row;
unsigned int row, col;
if ((vport->cursor_active) || (anims_enabled))
callid = async_get_call_timeout(&call, 250000);
1603,8 → 1601,8
case FB_PUTCHAR:
ch = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1622,8 → 1620,8
retval = EOK;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1643,7 → 1641,7
retval = EOK;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, vport->cols, vport->rows);
ipc_answer_2(callid, EOK, vport->rows, vport->cols);
continue;
case FB_SCROLL:
scroll = IPC_GET_ARG1(call);
/branches/network/uspace/srv/fb/ega.c
49,8 → 49,8
#include <ipc/ns.h>
#include <ipc/services.h>
#include <libarch/ddi.h>
#include <io/style.h>
#include <io/color.h>
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
 
#include "ega.h"
70,7 → 70,7
int ega_normal_color = 0x0f;
int ega_inverted_color = 0xf0;
 
#define NORMAL_COLOR ega_normal_color
#define NORMAL_COLOR ega_normal_color
#define INVERTED_COLOR ega_inverted_color
 
/* Allow only 1 connection */
87,7 → 87,7
 
static void clrscr(void)
{
unsigned i;
int i;
for (i = 0; i < scr_width * scr_height; i++) {
scr_addr[i * 2] = ' ';
95,7 → 95,7
}
}
 
static void cursor_goto(unsigned int col, unsigned int row)
static void cursor_goto(unsigned int row, unsigned int col)
{
int ega_cursor;
 
129,8 → 129,7
 
static void scroll(int rows)
{
unsigned i;
 
int i;
if (rows > 0) {
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
scr_width * scr_height * 2 - rows * scr_width * 2);
145,12 → 144,12
}
}
 
static void printchar(wchar_t c, unsigned int col, unsigned int row)
static void printchar(wchar_t c, unsigned int row, unsigned int col)
{
scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
scr_addr[(row * scr_width + col) * 2 + 1] = style;
cursor_goto(col + 1, row);
cursor_goto(row, col + 1);
}
 
/** Draw text data to viewport.
242,15 → 241,11
static unsigned attr_to_ega_style(const attrs_t *a)
{
switch (a->t) {
case at_style:
return style_to_ega_style(a->a.s.style);
case at_rgb:
return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx:
return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default:
return INVERTED_COLOR;
case at_style: return style_to_ega_style(a->a.s.style);
case at_rgb: return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx: return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default: return INVERTED_COLOR;
}
}
 
317,7 → 312,7
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
ipc_answer_2(callid, EOK, scr_height, scr_width);
continue;
case FB_CLEAR:
clrscr();
325,28 → 320,28
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if (col >= scr_width || row >= scr_height) {
retval = EINVAL;
break;
}
printchar(c, col, row);
printchar(c, row, col);
retval = 0;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
if (row >= scr_height || col >= scr_width) {
retval = EINVAL;
break;
}
cursor_goto(col, row);
cursor_goto(row, col);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if (i > (int) scr_height || i < -((int) scr_height)) {
if (i > scr_height || i < -((int) scr_height)) {
retval = EINVAL;
break;
}
/branches/network/uspace/srv/fb/serial_console.h
43,7 → 43,7
typedef void (*putc_function_t)(char);
 
void serial_puts(char *str);
void serial_goto(const unsigned int col, const unsigned int row);
void serial_goto(const unsigned int row, const unsigned int col);
void serial_clrscr(void);
void serial_scroll(int i);
void serial_cursor_disable(void);
/branches/network/uspace/srv/fb/ppm.c
89,7 → 89,7
{
unsigned int width, height;
unsigned int maxcolor;
unsigned i;
int i;
unsigned int color;
unsigned int coef;
/branches/network/uspace/srv/fb/Makefile
34,8 → 34,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
CFLAGS += -I../libipc/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
103,7 → 105,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/fb/ega.h
27,10 → 27,10
*/
 
/** @addtogroup egafb
* @brief HelenOS EGA framebuffer.
* @brief HelenOS EGA framebuffer.
* @ingroup fbs
* @{
*/
*/
/** @file
*/
 
43,3 → 43,4
 
/** @}
*/
 
/branches/network/uspace/srv/fs/devfs/devfs.c
File deleted
/branches/network/uspace/srv/fs/devfs/devfs_ops.c
File deleted
/branches/network/uspace/srv/fs/devfs/devfs.h
File deleted
/branches/network/uspace/srv/fs/devfs/Makefile
File deleted
/branches/network/uspace/srv/fs/devfs/devfs_ops.h
File deleted
/branches/network/uspace/srv/fs/tmpfs/tmpfs.h
38,15 → 38,12
#include <atomic.h>
#include <sys/types.h>
#include <bool.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#ifndef dprintf
#define dprintf(...) printf(__VA_ARGS__)
#endif
 
#define TMPFS_NODE(node) ((node) ? (tmpfs_node_t *)(node)->data : NULL)
#define FS_NODE(node) ((node) ? (node)->bp : NULL)
 
typedef enum {
TMPFS_NONE,
TMPFS_FILE,
53,26 → 50,18
TMPFS_DIRECTORY
} tmpfs_dentry_type_t;
 
/* forward declaration */
struct tmpfs_node;
 
typedef struct tmpfs_dentry {
link_t link; /**< Linkage for the list of siblings. */
struct tmpfs_node *node;/**< Back pointer to TMPFS node. */
char *name; /**< Name of dentry. */
} tmpfs_dentry_t;
 
typedef struct tmpfs_node {
fs_node_t *bp; /**< Back pointer to the FS node. */
fs_index_t index; /**< TMPFS node index. */
dev_handle_t dev_handle;/**< Device handle. */
link_t nh_link; /**< Nodes hash table link. */
link_t dh_link; /**< Dentries hash table link. */
struct tmpfs_dentry *sibling;
struct tmpfs_dentry *child;
hash_table_t names; /**< All names linking to this TMPFS node. */
tmpfs_dentry_type_t type;
unsigned lnkcnt; /**< Link count. */
size_t size; /**< File size if type is TMPFS_FILE. */
void *data; /**< File content's if type is TMPFS_FILE. */
link_t cs_head; /**< Head of child's siblings list. */
} tmpfs_node_t;
} tmpfs_dentry_t;
 
extern fs_reg_t tmpfs_reg;
 
86,11 → 75,7
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_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
54,8 → 54,8
} __attribute__((packed));
 
static bool
tmpfs_restore_recursion(dev_handle_t dev, off_t *bufpos, size_t *buflen,
off_t *pos, fs_node_t *pfn)
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos,
tmpfs_dentry_t *parent)
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
63,8 → 63,7
do {
char *fname;
fs_node_t *fn;
tmpfs_node_t *nodep;
tmpfs_dentry_t *node;
uint32_t size;
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
81,8 → 80,8
if (fname == NULL)
return false;
fn = ops->create(dev, L_FILE);
if (fn == NULL) {
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE);
if (node == NULL) {
free(fname);
return false;
}
89,15 → 88,15
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
ops->destroy((void *) node);
free(fname);
return false;
}
fname[entry.len] = 0;
rc = ops->link(pfn, fn, fname);
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy(fn);
ops->destroy((void *) node);
free(fname);
return false;
}
109,13 → 108,12
size = uint32_t_le2host(size);
nodep = TMPFS_NODE(fn);
nodep->data = malloc(size);
if (nodep->data == NULL)
node->data = malloc(size);
if (node->data == NULL)
return false;
nodep->size = size;
if (block_read(dev, bufpos, buflen, pos, nodep->data,
node->size = size;
if (block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE) != EOK)
return false;
125,8 → 123,8
if (fname == NULL)
return false;
fn = ops->create(dev, L_DIRECTORY);
if (fn == NULL) {
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY);
if (node == NULL) {
free(fname);
return false;
}
133,15 → 131,15
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
ops->destroy((void *) node);
free(fname);
return false;
}
fname[entry.len] = 0;
 
rc = ops->link(pfn, fn, fname);
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy(fn);
ops->destroy((void *) node);
free(fname);
return false;
}
148,7 → 146,7
free(fname);
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
fn))
node))
return false;
break;
/branches/network/uspace/srv/fs/tmpfs/tmpfs.c
96,8 → 96,6
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
return;
case VFS_MOUNTED:
tmpfs_mounted(callid, &call);
break;
116,21 → 114,9
case VFS_TRUNCATE:
tmpfs_truncate(callid, &call);
break;
case VFS_CLOSE:
tmpfs_close(callid, &call);
break;
case VFS_DESTROY:
tmpfs_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
tmpfs_open_node(callid, &call);
break;
case VFS_DEVICE:
tmpfs_device(callid, &call);
break;
case VFS_SYNC:
tmpfs_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/network/uspace/srv/fs/tmpfs/tmpfs_ops.c
47,7 → 47,7
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <as.h>
#include <libfs.h>
 
54,8 → 54,10
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
 
#define NODES_BUCKETS 256
#define DENTRIES_BUCKETS 256
 
#define NAMES_BUCKETS 4
 
/** All root nodes have index 0. */
#define TMPFS_SOME_ROOT 0
/** Global counter for assigning node indices. Shared by all instances. */
66,36 → 68,36
*/
 
/* Forward declarations of static functions. */
static fs_node_t *tmpfs_match(fs_node_t *, const char *);
static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t);
static void tmpfs_node_put(fs_node_t *);
static fs_node_t *tmpfs_create_node(dev_handle_t, int);
static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *);
static int tmpfs_destroy_node(fs_node_t *);
static void *tmpfs_match(void *, const char *);
static void *tmpfs_node_get(dev_handle_t, fs_index_t);
static void tmpfs_node_put(void *);
static void *tmpfs_create_node(dev_handle_t, int);
static int tmpfs_link_node(void *, void *, const char *);
static int tmpfs_unlink_node(void *, void *);
static int tmpfs_destroy_node(void *);
 
/* Implementation of helper functions. */
static fs_index_t tmpfs_index_get(fs_node_t *fn)
static fs_index_t tmpfs_index_get(void *nodep)
{
return TMPFS_NODE(fn)->index;
return ((tmpfs_dentry_t *) nodep)->index;
}
 
static size_t tmpfs_size_get(fs_node_t *fn)
static size_t tmpfs_size_get(void *nodep)
{
return TMPFS_NODE(fn)->size;
return ((tmpfs_dentry_t *) nodep)->size;
}
 
static unsigned tmpfs_lnkcnt_get(fs_node_t *fn)
static unsigned tmpfs_lnkcnt_get(void *nodep)
{
return TMPFS_NODE(fn)->lnkcnt;
return ((tmpfs_dentry_t *) nodep)->lnkcnt;
}
 
static bool tmpfs_has_children(fs_node_t *fn)
static bool tmpfs_has_children(void *nodep)
{
return !list_empty(&TMPFS_NODE(fn)->cs_head);
return ((tmpfs_dentry_t *) nodep)->child != NULL;
}
 
static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle)
static void *tmpfs_root_get(dev_handle_t dev_handle)
{
return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT);
}
105,14 → 107,14
return tmpfs_reg.plb_ro[pos % PLB_SIZE];
}
 
static bool tmpfs_is_directory(fs_node_t *fn)
static bool tmpfs_is_directory(void *nodep)
{
return TMPFS_NODE(fn)->type == TMPFS_DIRECTORY;
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY;
}
 
static bool tmpfs_is_file(fs_node_t *fn)
static bool tmpfs_is_file(void *nodep)
{
return TMPFS_NODE(fn)->type == TMPFS_FILE;
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE;
}
 
/** libfs operations */
134,60 → 136,99
.is_file = tmpfs_is_file
};
 
/** Hash table of all TMPFS nodes. */
hash_table_t nodes;
/** Hash table of all directory entries. */
hash_table_t dentries;
 
#define NODES_KEY_INDEX 0
#define NODES_KEY_DEV 1
#define DENTRIES_KEY_INDEX 0
#define DENTRIES_KEY_DEV 1
 
/* Implementation of hash table interface for the nodes hash table. */
static hash_index_t nodes_hash(unsigned long key[])
/* Implementation of hash table interface for the dentries hash table. */
static hash_index_t dentries_hash(unsigned long key[])
{
return key[NODES_KEY_INDEX] % NODES_BUCKETS;
return key[DENTRIES_KEY_INDEX] % DENTRIES_BUCKETS;
}
 
static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
static int dentries_compare(unsigned long key[], hash_count_t keys,
link_t *item)
{
tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
nh_link);
return (nodep->index == key[NODES_KEY_INDEX] &&
nodep->dev_handle == key[NODES_KEY_DEV]);
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t,
dh_link);
return (dentry->index == key[DENTRIES_KEY_INDEX] &&
dentry->dev_handle == key[DENTRIES_KEY_DEV]);
}
 
static void nodes_remove_callback(link_t *item)
static void dentries_remove_callback(link_t *item)
{
}
 
/** TMPFS nodes hash table operations. */
hash_table_operations_t nodes_ops = {
.hash = nodes_hash,
.compare = nodes_compare,
.remove_callback = nodes_remove_callback
/** TMPFS dentries hash table operations. */
hash_table_operations_t dentries_ops = {
.hash = dentries_hash,
.compare = dentries_compare,
.remove_callback = dentries_remove_callback
};
 
static void tmpfs_node_initialize(tmpfs_node_t *nodep)
typedef struct {
char *name;
tmpfs_dentry_t *parent;
link_t link;
} tmpfs_name_t;
 
/* Implementation of hash table interface for the names hash table. */
static hash_index_t names_hash(unsigned long *key)
{
nodep->bp = NULL;
nodep->index = 0;
nodep->dev_handle = 0;
nodep->type = TMPFS_NONE;
nodep->lnkcnt = 0;
nodep->size = 0;
nodep->data = NULL;
link_initialize(&nodep->nh_link);
list_initialize(&nodep->cs_head);
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key;
return dentry->index % NAMES_BUCKETS;
}
 
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentryp)
static int names_compare(unsigned long *key, hash_count_t keys, link_t *item)
{
link_initialize(&dentryp->link);
dentryp->name = NULL;
dentryp->node = NULL;
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key;
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t,
link);
return dentry == namep->parent;
}
 
static void names_remove_callback(link_t *item)
{
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t,
link);
free(namep->name);
free(namep);
}
 
/** TMPFS node names hash table operations. */
static hash_table_operations_t names_ops = {
.hash = names_hash,
.compare = names_compare,
.remove_callback = names_remove_callback
};
 
static void tmpfs_name_initialize(tmpfs_name_t *namep)
{
namep->name = NULL;
namep->parent = NULL;
link_initialize(&namep->link);
}
 
static bool tmpfs_dentry_initialize(tmpfs_dentry_t *dentry)
{
dentry->index = 0;
dentry->dev_handle = 0;
dentry->sibling = NULL;
dentry->child = NULL;
dentry->type = TMPFS_NONE;
dentry->lnkcnt = 0;
dentry->size = 0;
dentry->data = NULL;
link_initialize(&dentry->dh_link);
return (bool)hash_table_create(&dentry->names, NAMES_BUCKETS, 1,
&names_ops);
}
 
bool tmpfs_init(void)
{
if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 2, &dentries_ops))
return false;
return true;
195,170 → 236,181
 
static bool tmpfs_instance_init(dev_handle_t dev_handle)
{
fs_node_t *rfn;
tmpfs_dentry_t *root;
rfn = tmpfs_create_node(dev_handle, L_DIRECTORY);
if (!rfn)
root = (tmpfs_dentry_t *) tmpfs_create_node(dev_handle, L_DIRECTORY);
if (!root)
return false;
TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */
root->lnkcnt = 0; /* FS root is not linked */
return true;
}
 
fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component)
/** Compare one component of path to a directory entry.
*
* @param parentp Pointer to node from which we descended.
* @param childp Pointer to node to compare the path component with.
* @param component Array of characters holding component name.
*
* @return True on match, false otherwise.
*/
static bool
tmpfs_match_one(tmpfs_dentry_t *parentp, tmpfs_dentry_t *childp,
const char *component)
{
tmpfs_node_t *parentp = TMPFS_NODE(pfn);
link_t *lnk;
unsigned long key = (unsigned long) parentp;
link_t *hlp = hash_table_find(&childp->names, &key);
assert(hlp);
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, link);
return !str_cmp(namep->name, component);
}
 
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
lnk = lnk->next) {
tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t,
link);
if (!str_cmp(dentryp->name, component))
return FS_NODE(dentryp->node);
}
void *tmpfs_match(void *prnt, const char *component)
{
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt;
tmpfs_dentry_t *childp = parentp->child;
 
return NULL;
while (childp && !tmpfs_match_one(parentp, childp, component))
childp = childp->sibling;
 
return (void *) childp;
}
 
fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index)
void *
tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index)
{
unsigned long key[] = {
[NODES_KEY_INDEX] = index,
[NODES_KEY_DEV] = dev_handle
[DENTRIES_KEY_INDEX] = index,
[DENTRIES_KEY_DEV] = dev_handle
};
link_t *lnk = hash_table_find(&nodes, key);
link_t *lnk = hash_table_find(&dentries, key);
if (!lnk)
return NULL;
return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link));
return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link);
}
 
void tmpfs_node_put(fs_node_t *fn)
void tmpfs_node_put(void *node)
{
/* nothing to do */
}
 
fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
void *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
{
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
 
tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t));
if (!nodep)
tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t));
if (!node)
return NULL;
tmpfs_node_initialize(nodep);
nodep->bp = malloc(sizeof(fs_node_t));
if (!nodep->bp) {
free(nodep);
 
if (!tmpfs_dentry_initialize(node)) {
free(node);
return NULL;
}
fs_node_initialize(nodep->bp);
nodep->bp->data = nodep; /* link the FS and TMPFS nodes */
if (!tmpfs_root_get(dev_handle))
nodep->index = TMPFS_SOME_ROOT;
node->index = TMPFS_SOME_ROOT;
else
nodep->index = tmpfs_next_index++;
nodep->dev_handle = dev_handle;
node->index = tmpfs_next_index++;
node->dev_handle = dev_handle;
if (lflag & L_DIRECTORY)
nodep->type = TMPFS_DIRECTORY;
node->type = TMPFS_DIRECTORY;
else
nodep->type = TMPFS_FILE;
node->type = TMPFS_FILE;
 
/* Insert the new node into the nodes hash table. */
/* Insert the new node into the dentry hash table. */
unsigned long key[] = {
[NODES_KEY_INDEX] = nodep->index,
[NODES_KEY_DEV] = nodep->dev_handle
[DENTRIES_KEY_INDEX] = node->index,
[DENTRIES_KEY_DEV] = node->dev_handle
};
hash_table_insert(&nodes, key, &nodep->nh_link);
return FS_NODE(nodep);
hash_table_insert(&dentries, key, &node->dh_link);
return (void *) node;
}
 
int tmpfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
int tmpfs_link_node(void *prnt, void *chld, const char *nm)
{
tmpfs_node_t *parentp = TMPFS_NODE(pfn);
tmpfs_node_t *childp = TMPFS_NODE(cfn);
tmpfs_dentry_t *dentryp;
link_t *lnk;
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt;
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld;
 
assert(parentp->type == TMPFS_DIRECTORY);
 
/* Check for duplicit entries. */
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
lnk = lnk->next) {
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
if (!str_cmp(dentryp->name, nm))
return EEXIST;
}
 
/* Allocate and initialize the dentry. */
dentryp = malloc(sizeof(tmpfs_dentry_t));
if (!dentryp)
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t));
if (!namep)
return ENOMEM;
tmpfs_dentry_initialize(dentryp);
 
/* Populate and link the new dentry. */
tmpfs_name_initialize(namep);
size_t size = str_size(nm);
dentryp->name = malloc(size + 1);
if (!dentryp->name) {
free(dentryp);
namep->name = malloc(size + 1);
if (!namep->name) {
free(namep);
return ENOMEM;
}
str_cpy(dentryp->name, size + 1, nm);
dentryp->node = childp;
str_cpy(namep->name, size + 1, nm);
namep->parent = parentp;
childp->lnkcnt++;
list_append(&dentryp->link, &parentp->cs_head);
 
unsigned long key = (unsigned long) parentp;
hash_table_insert(&childp->names, &key, &namep->link);
 
/* Insert the new node into the namespace. */
if (parentp->child) {
tmpfs_dentry_t *tmp = parentp->child;
while (tmp->sibling)
tmp = tmp->sibling;
tmp->sibling = childp;
} else {
parentp->child = childp;
}
 
return EOK;
}
 
int tmpfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
int tmpfs_unlink_node(void *prnt, void *chld)
{
tmpfs_node_t *parentp = TMPFS_NODE(pfn);
tmpfs_node_t *childp = NULL;
tmpfs_dentry_t *dentryp;
link_t *lnk;
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *)prnt;
tmpfs_dentry_t *childp = (tmpfs_dentry_t *)chld;
 
if (!parentp)
return EBUSY;
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
lnk = lnk->next) {
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
if (!str_cmp(dentryp->name, nm)) {
childp = dentryp->node;
assert(FS_NODE(childp) == cfn);
break;
}
}
 
if (!childp)
return ENOENT;
if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
if (childp->child)
return ENOTEMPTY;
 
list_remove(&dentryp->link);
free(dentryp);
if (parentp->child == childp) {
parentp->child = childp->sibling;
} else {
/* TODO: consider doubly linked list for organizing siblings. */
tmpfs_dentry_t *tmp = parentp->child;
while (tmp->sibling != childp)
tmp = tmp->sibling;
tmp->sibling = childp->sibling;
}
childp->sibling = NULL;
 
unsigned long key = (unsigned long) parentp;
hash_table_remove(&childp->names, &key, 1);
 
childp->lnkcnt--;
 
return EOK;
}
 
int tmpfs_destroy_node(fs_node_t *fn)
int tmpfs_destroy_node(void *nodep)
{
tmpfs_node_t *nodep = TMPFS_NODE(fn);
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep;
assert(!nodep->lnkcnt);
assert(list_empty(&nodep->cs_head));
assert(!dentry->lnkcnt);
assert(!dentry->child);
assert(!dentry->sibling);
 
unsigned long key[] = {
[NODES_KEY_INDEX] = nodep->index,
[NODES_KEY_DEV] = nodep->dev_handle
[DENTRIES_KEY_INDEX] = dentry->index,
[DENTRIES_KEY_DEV] = dentry->dev_handle
};
hash_table_remove(&nodes, key, 2);
hash_table_remove(&dentries, key, 2);
 
if (nodep->type == TMPFS_FILE)
free(nodep->data);
free(nodep->bp);
free(nodep);
hash_table_destroy(&dentry->names);
 
if (dentry->type == TMPFS_FILE)
free(dentry->data);
free(dentry);
return EOK;
}
 
394,22 → 446,26
return;
}
 
tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle));
tmpfs_dentry_t *root = tmpfs_root_get(dev_handle);
if (str_cmp(opts, "restore") == 0) {
if (tmpfs_restore(dev_handle))
ipc_answer_3(rid, EOK, rootp->index, rootp->size,
rootp->lnkcnt);
ipc_answer_3(rid, EOK, root->index, root->size,
root->lnkcnt);
else
ipc_answer_0(rid, ELIMIT);
} else {
ipc_answer_3(rid, EOK, rootp->index, rootp->size,
rootp->lnkcnt);
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt);
}
}
 
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t mp_index = (fs_index_t) IPC_GET_ARG2(*request);
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request);
ipc_answer_0(rid, ENOTSUP);
}
 
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
424,20 → 480,20
off_t pos = (off_t)IPC_GET_ARG3(*request);
 
/*
* Lookup the respective TMPFS node.
* Lookup the respective dentry.
*/
link_t *hlp;
unsigned long key[] = {
[NODES_KEY_INDEX] = index,
[NODES_KEY_DEV] = dev_handle,
[DENTRIES_KEY_INDEX] = index,
[DENTRIES_KEY_DEV] = dev_handle,
};
hlp = hash_table_find(&nodes, key);
hlp = hash_table_find(&dentries, key);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
nh_link);
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
 
/*
* Receive the read request.
451,16 → 507,15
}
 
size_t bytes;
if (nodep->type == TMPFS_FILE) {
bytes = max(0, min(nodep->size - pos, size));
(void) ipc_data_read_finalize(callid, nodep->data + pos,
if (dentry->type == TMPFS_FILE) {
bytes = max(0, min(dentry->size - pos, size));
(void) ipc_data_read_finalize(callid, dentry->data + pos,
bytes);
} else {
tmpfs_dentry_t *dentryp;
link_t *lnk;
int i;
tmpfs_dentry_t *cur;
assert(nodep->type == TMPFS_DIRECTORY);
assert(dentry->type == TMPFS_DIRECTORY);
/*
* Yes, we really use O(n) algorithm here.
467,21 → 522,24
* If it bothers someone, it could be fixed by introducing a
* hash table.
*/
for (i = 0, lnk = nodep->cs_head.next;
i < pos && lnk != &nodep->cs_head;
i++, lnk = lnk->next)
for (i = 0, cur = dentry->child; i < pos && cur; i++,
cur = cur->sibling)
;
 
if (lnk == &nodep->cs_head) {
if (!cur) {
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
}
 
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
unsigned long key = (unsigned long) dentry;
link_t *hlp = hash_table_find(&cur->names, &key);
assert(hlp);
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t,
link);
 
(void) ipc_data_read_finalize(callid, dentryp->name,
str_size(dentryp->name) + 1);
(void) ipc_data_read_finalize(callid, namep->name,
str_size(namep->name) + 1);
bytes = 1;
}
 
498,20 → 556,20
off_t pos = (off_t)IPC_GET_ARG3(*request);
 
/*
* Lookup the respective TMPFS node.
* Lookup the respective dentry.
*/
link_t *hlp;
unsigned long key[] = {
[NODES_KEY_INDEX] = index,
[NODES_KEY_DEV] = dev_handle
[DENTRIES_KEY_INDEX] = index,
[DENTRIES_KEY_DEV] = dev_handle
};
hlp = hash_table_find(&nodes, key);
hlp = hash_table_find(&dentries, key);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
nh_link);
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
 
/*
* Receive the write request.
527,13 → 585,13
/*
* Check whether the file needs to grow.
*/
if (pos + size <= nodep->size) {
if (pos + size <= dentry->size) {
/* The file size is not changing. */
(void) ipc_data_write_finalize(callid, nodep->data + pos, size);
ipc_answer_2(rid, EOK, size, nodep->size);
(void) ipc_data_write_finalize(callid, dentry->data + pos, size);
ipc_answer_2(rid, EOK, size, dentry->size);
return;
}
size_t delta = (pos + size) - nodep->size;
size_t delta = (pos + size) - dentry->size;
/*
* At this point, we are deliberately extremely straightforward and
* simply realloc the contents of the file on every write that grows the
541,18 → 599,18
* our heap allocator can save us and just grow the block whenever
* possible.
*/
void *newdata = realloc(nodep->data, nodep->size + delta);
void *newdata = realloc(dentry->data, dentry->size + delta);
if (!newdata) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_2(rid, EOK, 0, nodep->size);
ipc_answer_2(rid, EOK, 0, dentry->size);
return;
}
/* Clear any newly allocated memory in order to emulate gaps. */
memset(newdata + nodep->size, 0, delta);
nodep->size += delta;
nodep->data = newdata;
(void) ipc_data_write_finalize(callid, nodep->data + pos, size);
ipc_answer_2(rid, EOK, size, nodep->size);
memset(newdata + dentry->size, 0, delta);
dentry->size += delta;
dentry->data = newdata;
(void) ipc_data_write_finalize(callid, dentry->data + pos, size);
ipc_answer_2(rid, EOK, size, dentry->size);
}
 
void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
562,45 → 620,40
size_t size = (off_t)IPC_GET_ARG3(*request);
 
/*
* Lookup the respective TMPFS node.
* Lookup the respective dentry.
*/
link_t *hlp;
unsigned long key[] = {
[NODES_KEY_INDEX] = index,
[NODES_KEY_DEV] = dev_handle
[DENTRIES_KEY_INDEX] = index,
[DENTRIES_KEY_DEV] = dev_handle
};
hlp = hash_table_find(&nodes, key);
hlp = hash_table_find(&dentries, key);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
nh_link);
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
 
if (size == nodep->size) {
if (size == dentry->size) {
ipc_answer_0(rid, EOK);
return;
}
 
void *newdata = realloc(nodep->data, size);
void *newdata = realloc(dentry->data, size);
if (!newdata) {
ipc_answer_0(rid, ENOMEM);
return;
}
if (size > nodep->size) {
size_t delta = size - nodep->size;
memset(newdata + nodep->size, 0, delta);
if (size > dentry->size) {
size_t delta = size - dentry->size;
memset(newdata + dentry->size, 0, delta);
}
nodep->size = size;
nodep->data = newdata;
dentry->size = size;
dentry->data = newdata;
ipc_answer_0(rid, EOK);
}
 
void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
609,36 → 662,20
 
link_t *hlp;
unsigned long key[] = {
[NODES_KEY_INDEX] = index,
[NODES_KEY_DEV] = dev_handle
[DENTRIES_KEY_INDEX] = index,
[DENTRIES_KEY_DEV] = dev_handle
};
hlp = hash_table_find(&nodes, key);
hlp = hash_table_find(&dentries, key);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
nh_link);
rc = tmpfs_destroy_node(FS_NODE(nodep));
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
rc = tmpfs_destroy_node(dentry);
ipc_answer_0(rid, rc);
}
 
void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_device(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
}
 
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/network/uspace/srv/fs/tmpfs/Makefile
72,7 → 72,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/fs/fat/fat_dentry.c
114,51 → 114,37
 
void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
{
unsigned int i;
int i;
 
for (i = 0; i < FAT_NAME_LEN; i++) {
if (d->name[i] == FAT_PAD)
break;
if (d->name[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else {
if (d->lcase & FAT_LCASE_LOWER_NAME)
*buf++ = tolower(d->name[i]);
else
*buf++ = d->name[i];
}
else
*buf++ = d->name[i];
}
if (d->ext[0] != FAT_PAD)
*buf++ = '.';
for (i = 0; i < FAT_EXT_LEN; i++) {
if (d->ext[i] == FAT_PAD) {
*buf = '\0';
return;
}
if (d->ext[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else {
if (d->lcase & FAT_LCASE_LOWER_EXT)
*buf++ = tolower(d->ext[i]);
else
*buf++ = d->ext[i];
}
else
*buf++ = d->ext[i];
}
*buf = '\0';
}
 
void fat_dentry_name_set(fat_dentry_t *d, const char *name)
{
unsigned int i;
int i;
const char fake_ext[] = " ";
bool lower_name = true;
bool lower_ext = true;
 
 
for (i = 0; i < FAT_NAME_LEN; i++) {
switch ((uint8_t) *name) {
case 0xe5:
170,19 → 156,12
d->name[i] = FAT_PAD;
break;
default:
if (isalpha(*name)) {
if (!islower(*name))
lower_name = false;
}
d->name[i] = toupper(*name++);
break;
}
}
if (*name++ != '.')
name = fake_ext;
for (i = 0; i < FAT_EXT_LEN; i++) {
switch ((uint8_t) *name) {
case 0xe5:
193,25 → 172,10
d->ext[i] = FAT_PAD;
break;
default:
if (isalpha(*name)) {
if (!islower(*name))
lower_ext = false;
}
d->ext[i] = toupper(*name++);
break;
}
}
if (lower_name)
d->lcase |= FAT_LCASE_LOWER_NAME;
else
d->lcase &= ~FAT_LCASE_LOWER_NAME;
if (lower_ext)
d->lcase |= FAT_LCASE_LOWER_EXT;
else
d->lcase &= ~FAT_LCASE_LOWER_EXT;
}
 
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
/branches/network/uspace/srv/fs/fat/fat_ops.c
48,26 → 48,22
#include <errno.h>
#include <string.h>
#include <byteorder.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <assert.h>
#include <fibril_sync.h>
#include <futex.h>
#include <sys/mman.h>
#include <align.h>
 
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL)
#define FS_NODE(node) ((node) ? (node)->bp : NULL)
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
 
/** Mutex protecting the list of cached free FAT nodes. */
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
 
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
 
static void fat_node_initialize(fat_node_t *node)
{
fibril_mutex_initialize(&node->lock);
node->bp = NULL;
futex_initialize(&node->lock, 1);
node->idx = NULL;
node->type = 0;
link_initialize(&node->ffn_link);
112,46 → 108,36
 
static fat_node_t *fat_node_get_new(void)
{
fs_node_t *fn;
fat_node_t *nodep;
 
fibril_mutex_lock(&ffn_mutex);
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (!fibril_mutex_trylock(&nodep->lock))
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
fibril_mutex_unlock(&nodep->lock);
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
fibril_mutex_unlock(&ffn_mutex);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
fibril_mutex_unlock(&nodep->lock);
fibril_mutex_unlock(&idxp_tmp->lock);
fn = FS_NODE(nodep);
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
fibril_mutex_unlock(&ffn_mutex);
fn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!fn)
return NULL;
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep) {
free(fn);
if (!nodep)
return NULL;
}
}
fat_node_initialize(nodep);
fs_node_initialize(fn);
fn->data = nodep;
nodep->bp = fn;
return nodep;
}
160,7 → 146,7
*
* @param idxp Locked index structure.
*/
static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
static void *fat_node_get_core(fat_idx_t *idxp)
{
block_t *b;
fat_bs_t *bs;
175,10 → 161,10
* We are lucky.
* The node is already instantiated in memory.
*/
fibril_mutex_lock(&idxp->nodep->lock);
futex_down(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&idxp->nodep->ffn_link);
fibril_mutex_unlock(&idxp->nodep->lock);
futex_up(&idxp->nodep->lock);
return idxp->nodep;
}
 
237,21 → 223,21
/*
* Forward declarations of FAT libfs operations.
*/
static fs_node_t *fat_node_get(dev_handle_t, fs_index_t);
static void fat_node_put(fs_node_t *);
static fs_node_t *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(fs_node_t *);
static int fat_link(fs_node_t *, fs_node_t *, const char *);
static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
static fs_node_t *fat_match(fs_node_t *, const char *);
static fs_index_t fat_index_get(fs_node_t *);
static size_t fat_size_get(fs_node_t *);
static unsigned fat_lnkcnt_get(fs_node_t *);
static bool fat_has_children(fs_node_t *);
static fs_node_t *fat_root_get(dev_handle_t);
static void *fat_node_get(dev_handle_t, fs_index_t);
static void fat_node_put(void *);
static void *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(void *);
static int fat_link(void *, void *, const char *);
static int fat_unlink(void *, void *);
static void *fat_match(void *, const char *);
static fs_index_t fat_index_get(void *);
static size_t fat_size_get(void *);
static unsigned fat_lnkcnt_get(void *);
static bool fat_has_children(void *);
static void *fat_root_get(dev_handle_t);
static char fat_plb_get_char(unsigned);
static bool fat_is_directory(fs_node_t *);
static bool fat_is_file(fs_node_t *node);
static bool fat_is_directory(void *);
static bool fat_is_file(void *node);
 
/*
* FAT libfs operations.
258,9 → 244,9
*/
 
/** Instantiate a FAT in-core node. */
fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
{
fat_node_t *nodep;
void *node;
fat_idx_t *idxp;
 
idxp = fat_idx_get_by_index(dev_handle, index);
267,22 → 253,22
if (!idxp)
return NULL;
/* idxp->lock held */
nodep = fat_node_get_core(idxp);
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
node = fat_node_get_core(idxp);
futex_up(&idxp->lock);
return node;
}
 
void fat_node_put(fs_node_t *fn)
void fat_node_put(void *node)
{
fat_node_t *nodep = FAT_NODE(fn);
fat_node_t *nodep = (fat_node_t *)node;
bool destroy = false;
 
fibril_mutex_lock(&nodep->lock);
futex_down(&nodep->lock);
if (!--nodep->refcnt) {
if (nodep->idx) {
fibril_mutex_lock(&ffn_mutex);
futex_down(&ffn_futex);
list_append(&nodep->ffn_link, &ffn_head);
fibril_mutex_unlock(&ffn_mutex);
futex_up(&ffn_futex);
} else {
/*
* The node does not have any index structure associated
293,14 → 279,12
destroy = true;
}
}
fibril_mutex_unlock(&nodep->lock);
if (destroy) {
free(nodep->bp);
free(nodep);
}
futex_up(&nodep->lock);
if (destroy)
free(node);
}
 
fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags)
void *fat_create_node(dev_handle_t dev_handle, int flags)
{
fat_idx_t *idxp;
fat_node_t *nodep;
326,7 → 310,7
idxp = fat_idx_get_new(dev_handle);
if (!idxp) {
fat_free_clusters(bs, dev_handle, mcl);
fat_node_put(FS_NODE(nodep));
fat_node_put(nodep);
return NULL;
}
/* idxp->lock held */
360,13 → 344,13
nodep->idx = idxp;
idxp->nodep = nodep;
 
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
futex_up(&idxp->lock);
return nodep;
}
 
int fat_destroy_node(fs_node_t *fn)
int fat_destroy_node(void *node)
{
fat_node_t *nodep = FAT_NODE(fn);
fat_node_t *nodep = (fat_node_t *)node;
fat_bs_t *bs;
 
/*
380,7 → 364,7
/*
* The node may not have any children.
*/
assert(fat_has_children(fn) == false);
assert(fat_has_children(node) == false);
 
bs = block_bb_get(nodep->idx->dev_handle);
if (nodep->firstc != FAT_CLST_RES0) {
390,15 → 374,14
}
 
fat_idx_destroy(nodep->idx);
free(nodep->bp);
free(nodep);
return EOK;
}
 
int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
int fat_link(void *prnt, void *chld, const char *name)
{
fat_node_t *parentp = FAT_NODE(pfn);
fat_node_t *childp = FAT_NODE(cfn);
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_dentry_t *d;
fat_bs_t *bs;
block_t *b;
409,16 → 392,16
fat_cluster_t mcl, lcl;
int rc;
 
fibril_mutex_lock(&childp->lock);
futex_down(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
432,7 → 415,7
* a new one.
*/
fibril_mutex_lock(&parentp->idx->lock);
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
463,12 → 446,12
*/
if (parentp->idx->pfc == FAT_CLST_ROOT) {
/* Can't grow the root directory. */
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return ENOSPC;
}
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
if (rc != EOK) {
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return rc;
}
fat_append_clusters(bs, parentp, mcl);
491,9 → 474,9
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
 
fibril_mutex_lock(&childp->idx->lock);
futex_down(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
529,12 → 512,12
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
fibril_mutex_unlock(&childp->idx->lock);
futex_up(&childp->idx->lock);
 
fibril_mutex_lock(&childp->lock);
futex_down(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
544,25 → 527,19
return EOK;
}
 
int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
int fat_unlink(void *prnt, void *chld)
{
fat_node_t *parentp = FAT_NODE(pfn);
fat_node_t *childp = FAT_NODE(cfn);
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
block_t *b;
 
if (!parentp)
return EBUSY;
if (fat_has_children(cfn))
return ENOTEMPTY;
 
fibril_mutex_lock(&parentp->lock);
fibril_mutex_lock(&childp->lock);
futex_down(&parentp->lock);
futex_down(&childp->lock);
assert(childp->lnkcnt == 1);
fibril_mutex_lock(&childp->idx->lock);
futex_down(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
581,19 → 558,19
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
fibril_mutex_unlock(&childp->idx->lock);
futex_up(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
fibril_mutex_unlock(&childp->lock);
fibril_mutex_unlock(&parentp->lock);
futex_up(&childp->lock);
futex_up(&parentp->lock);
 
return EOK;
}
 
fs_node_t *fat_match(fs_node_t *pfn, const char *component)
void *fat_match(void *prnt, const char *component)
{
fat_bs_t *bs;
fat_node_t *parentp = FAT_NODE(pfn);
fat_node_t *parentp = (fat_node_t *)prnt;
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
unsigned i, j;
unsigned bps; /* bytes per sector */
602,7 → 579,7
fat_dentry_t *d;
block_t *b;
 
fibril_mutex_lock(&parentp->idx->lock);
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
617,7 → 594,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return NULL;
default:
case FAT_DENTRY_VALID:
626,7 → 603,7
}
if (fat_dentry_namecmp(name, component) == 0) {
/* hit */
fat_node_t *nodep;
void *node;
/*
* Assume tree hierarchy for locking. We
* already have the parent and now we are going
636,7 → 613,7
fat_idx_t *idx = fat_idx_get_by_pos(
parentp->idx->dev_handle, parentp->firstc,
i * dps + j);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
if (!idx) {
/*
* Can happen if memory is low or if we
645,38 → 622,41
block_put(b);
return NULL;
}
nodep = fat_node_get_core(idx);
fibril_mutex_unlock(&idx->lock);
node = fat_node_get_core(idx);
futex_up(&idx->lock);
block_put(b);
return FS_NODE(nodep);
return node;
}
}
block_put(b);
}
 
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return NULL;
}
 
fs_index_t fat_index_get(fs_node_t *fn)
fs_index_t fat_index_get(void *node)
{
return FAT_NODE(fn)->idx->index;
fat_node_t *fnodep = (fat_node_t *)node;
if (!fnodep)
return 0;
return fnodep->idx->index;
}
 
size_t fat_size_get(fs_node_t *fn)
size_t fat_size_get(void *node)
{
return FAT_NODE(fn)->size;
return ((fat_node_t *)node)->size;
}
 
unsigned fat_lnkcnt_get(fs_node_t *fn)
unsigned fat_lnkcnt_get(void *node)
{
return FAT_NODE(fn)->lnkcnt;
return ((fat_node_t *)node)->lnkcnt;
}
 
bool fat_has_children(fs_node_t *fn)
bool fat_has_children(void *node)
{
fat_bs_t *bs;
fat_node_t *nodep = FAT_NODE(fn);
fat_node_t *nodep = (fat_node_t *)node;
unsigned bps;
unsigned dps;
unsigned blocks;
686,7 → 666,7
if (nodep->type != FAT_DIRECTORY)
return false;
fibril_mutex_lock(&nodep->idx->lock);
futex_down(&nodep->idx->lock);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
705,26 → 685,26
continue;
case FAT_DENTRY_LAST:
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
}
 
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return false;
}
 
fs_node_t *fat_root_get(dev_handle_t dev_handle)
void *fat_root_get(dev_handle_t dev_handle)
{
return fat_node_get(dev_handle, 0);
}
734,14 → 714,14
return fat_reg.plb_ro[pos % PLB_SIZE];
}
 
bool fat_is_directory(fs_node_t *fn)
bool fat_is_directory(void *node)
{
return FAT_NODE(fn)->type == FAT_DIRECTORY;
return ((fat_node_t *)node)->type == FAT_DIRECTORY;
}
 
bool fat_is_file(fs_node_t *fn)
bool fat_is_file(void *node)
{
return FAT_NODE(fn)->type == FAT_FILE;
return ((fat_node_t *)node)->type == FAT_FILE;
}
 
/** libfs operations */
770,7 → 750,6
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
enum cache_mode cmode;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
798,12 → 777,6
}
opts[size] = '\0';
 
/* Check for option enabling write through. */
if (str_cmp(opts, "wtcache") == 0)
cmode = CACHE_MODE_WT;
else
cmode = CACHE_MODE_WB;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
833,7 → 806,7
}
 
/* Initialize the block cache */
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode);
rc = block_cache_init(dev_handle, bps, 0 /* XXX */);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
848,17 → 821,8
}
 
/* Initialize the root node. */
fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!rfn) {
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
}
fs_node_initialize(rfn);
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
free(rfn);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
868,9 → 832,8
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
free(rfn);
block_fini(dev_handle);
free(rootp);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
885,10 → 848,8
rootp->size = rde * sizeof(fat_dentry_t);
rootp->idx = ridxp;
ridxp->nodep = rootp;
rootp->bp = rfn;
rfn->data = rootp;
fibril_mutex_unlock(&ridxp->lock);
futex_up(&ridxp->lock);
 
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
895,7 → 856,7
 
void fat_mount(ipc_callid_t rid, ipc_call_t *request)
{
libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
ipc_answer_0(rid, ENOTSUP);
}
 
void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
908,23 → 869,21
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fat_bs_t *bs;
uint16_t bps;
size_t bytes;
block_t *b;
 
if (!fn) {
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
 
ipc_callid_t callid;
size_t len;
if (!ipc_data_read_receive(&callid, &len)) {
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
995,7 → 954,7
bnum++;
}
miss:
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
1004,7 → 963,7
bytes = (pos - spos) + 1;
}
 
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
1013,8 → 972,7
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fat_bs_t *bs;
size_t bytes;
block_t *b;
1024,16 → 982,15
off_t boundary;
int flags = BLOCK_FLAGS_NONE;
if (!fn) {
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
ipc_callid_t callid;
size_t len;
if (!ipc_data_write_receive(&callid, &len)) {
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
1074,7 → 1031,7
nodep->dirty = true; /* need to sync node */
}
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(fn);
fat_node_put(nodep);
return;
} else {
/*
1090,7 → 1047,7
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);
if (status != EOK) {
/* could not allocate a chain of nclsts clusters */
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_0(callid, status);
ipc_answer_0(rid, status);
return;
1111,7 → 1068,7
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(fn);
fat_node_put(nodep);
return;
}
}
1121,8 → 1078,7
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
size_t size = (off_t)IPC_GET_ARG3(*request);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fat_bs_t *bs;
uint16_t bps;
uint8_t spc;
1129,11 → 1085,10
unsigned bpc; /* bytes per cluster */
int rc;
 
if (!fn) {
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
1171,16 → 1126,11
nodep->dirty = true; /* need to sync node */
rc = EOK;
}
fat_node_put(fn);
fat_node_put(nodep);
ipc_answer_0(rid, rc);
return;
}
 
void fat_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
1187,32 → 1137,16
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
int rc;
 
fs_node_t *fn = fat_node_get(dev_handle, index);
if (!fn) {
fat_node_t *nodep = fat_node_get(dev_handle, index);
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
 
rc = fat_destroy_node(fn);
rc = fat_destroy_node(nodep);
ipc_answer_0(rid, rc);
}
 
void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_device(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
}
 
void fat_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/network/uspace/srv/fs/fat/fat_idx.c
39,10 → 39,10
#include "../../vfs/vfs.h"
#include <errno.h>
#include <string.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <assert.h>
#include <fibril_sync.h>
#include <futex.h>
 
/** Each instance of this type describes one interval of freed VFS indices. */
typedef struct {
68,8 → 68,8
link_t freed_head;
} unused_t;
 
/** Mutex protecting the list of unused structures. */
static FIBRIL_MUTEX_INITIALIZE(unused_lock);
/** Futex protecting the list of unused structures. */
static futex_t unused_futex = FUTEX_INITIALIZER;
 
/** List of unused structures. */
static LIST_INITIALIZE(unused_head);
89,7 → 89,7
link_t *l;
 
if (lock)
fibril_mutex_lock(&unused_lock);
futex_down(&unused_futex);
for (l = unused_head.next; l != &unused_head; l = l->next) {
u = list_get_instance(l, unused_t, link);
if (u->dev_handle == dev_handle)
96,12 → 96,12
return u;
}
if (lock)
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return NULL;
}
 
/** Mutex protecting the up_hash and ui_hash. */
static FIBRIL_MUTEX_INITIALIZE(used_lock);
/** Futex protecting the up_hash and ui_hash. */
static futex_t used_futex = FUTEX_INITIALIZER;
 
/**
* Global hash table of all used fat_idx_t structures.
231,7 → 231,7
*/
*index = u->next++;
--u->remaining;
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return true;
}
} else {
244,7 → 244,7
list_remove(&f->link);
free(f);
}
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return true;
}
/*
252,7 → 252,7
* theoretically still possible (e.g. too many open unlinked nodes or
* too many zero-sized nodes).
*/
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return false;
}
 
302,7 → 302,7
if (lnk->prev != &u->freed_head)
try_coalesce_intervals(lnk->prev, lnk,
lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
if (f->last == index - 1) {
310,7 → 310,7
if (lnk->next != &u->freed_head)
try_coalesce_intervals(lnk, lnk->next,
lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
if (index > f->first) {
321,7 → 321,7
n->first = index;
n->last = index;
list_insert_before(&n->link, lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
 
335,7 → 335,7
n->last = index;
list_append(&n->link, &u->freed_head);
}
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
}
 
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
352,7 → 352,7
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
fibril_mutex_initialize(&fidx->lock);
futex_initialize(&fidx->lock, 1);
fidx->dev_handle = dev_handle;
fidx->pfc = FAT_CLST_RES0; /* no parent yet */
fidx->pdi = 0;
365,10 → 365,10
{
fat_idx_t *fidx;
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
fidx = fat_idx_create(dev_handle);
if (!fidx) {
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
return NULL;
}
378,8 → 378,8
};
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
futex_down(&fidx->lock);
futex_up(&used_futex);
 
return fidx;
}
395,7 → 395,7
[UPH_PDI_KEY] = pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
l = hash_table_find(&up_hash, pkey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
402,7 → 402,7
} else {
fidx = fat_idx_create(dev_handle);
if (!fidx) {
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
return NULL;
}
417,8 → 417,8
hash_table_insert(&up_hash, pkey, &fidx->uph_link);
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
}
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
futex_down(&fidx->lock);
futex_up(&used_futex);
 
return fidx;
}
431,9 → 431,9
[UPH_PDI_KEY] = idx->pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
hash_table_insert(&up_hash, pkey, &idx->uph_link);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
}
 
void fat_idx_hashout(fat_idx_t *idx)
444,9 → 444,9
[UPH_PDI_KEY] = idx->pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
hash_table_remove(&up_hash, pkey, 3);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
}
 
fat_idx_t *
459,13 → 459,13
[UIH_INDEX_KEY] = index,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
l = hash_table_find(&ui_hash, ikey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
fibril_mutex_lock(&fidx->lock);
futex_down(&fidx->lock);
}
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
 
return fidx;
}
483,7 → 483,7
 
assert(idx->pfc == FAT_CLST_RES0);
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
/*
* Since we can only free unlinked nodes, the index structure is not
* present in the position hash (uph). We therefore hash it out from
490,7 → 490,7
* the index hash only.
*/
hash_table_remove(&ui_hash, ikey, 2);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
/* Release the VFS index. */
fat_index_free(idx->dev_handle, idx->index);
/* Deallocate the structure. */
524,12 → 524,12
if (!u)
return ENOMEM;
unused_initialize(u, dev_handle);
fibril_mutex_lock(&unused_lock);
futex_down(&unused_futex);
if (!unused_find(dev_handle, false))
list_append(&u->link, &unused_head);
else
rc = EEXIST;
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return rc;
}
 
540,7 → 540,7
u = unused_find(dev_handle, true);
assert(u);
list_remove(&u->link);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
 
while (!list_empty(&u->freed_head)) {
freed_t *f;
/branches/network/uspace/srv/fs/fat/fat.h
35,7 → 35,6
 
#include "fat_fat.h"
#include <ipc/ipc.h>
#include <fibril_sync.h>
#include <libfs.h>
#include <atomic.h>
#include <sys/types.h>
161,7 → 160,7
/** Used indices (index) hash table link. */
link_t uih_link;
 
fibril_mutex_t lock;
futex_t lock;
dev_handle_t dev_handle;
fs_index_t index;
/**
179,10 → 178,7
 
/** FAT in-core node. */
typedef struct fat_node {
/** Back pointer to the FS node. */
fs_node_t *bp;
fibril_mutex_t lock;
futex_t lock;
fat_node_type_t type;
fat_idx_t *idx;
/**
207,11 → 203,7
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_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_sync(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_new(dev_handle_t);
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
/branches/network/uspace/srv/fs/fat/fat_dentry.h
47,9 → 47,6
#define FAT_ATTR_VOLLABEL (1 << 3)
#define FAT_ATTR_SUBDIR (1 << 4)
 
#define FAT_LCASE_LOWER_NAME 0x08
#define FAT_LCASE_LOWER_EXT 0x10
 
#define FAT_PAD ' '
 
#define FAT_DENTRY_UNUSED 0x00
68,7 → 65,7
uint8_t name[8];
uint8_t ext[3];
uint8_t attr;
uint8_t lcase;
uint8_t reserved;
uint8_t ctime_fine;
uint16_t ctime;
uint16_t cdate;
/branches/network/uspace/srv/fs/fat/fat_fat.c
45,15 → 45,14
#include <byteorder.h>
#include <align.h>
#include <assert.h>
#include <fibril_sync.h>
#include <mem.h>
#include <futex.h>
 
/**
* The fat_alloc_lock mutex protects all copies of the File Allocation Table
* The fat_alloc_lock futex protects all copies of the File Allocation Table
* during allocation of clusters. The lock does not have to be held durring
* deallocation of clusters.
*/
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
static futex_t fat_alloc_lock = FUTEX_INITIALIZER;
 
/** Walk the cluster chain.
*
326,7 → 325,7
/*
* Search FAT1 for unused clusters.
*/
fibril_mutex_lock(&fat_alloc_lock);
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; b++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
350,7 → 349,7
*mcl = lifo[found - 1];
*lcl = lifo[0];
free(lifo);
fibril_mutex_unlock(&fat_alloc_lock);
futex_up(&fat_alloc_lock);
return EOK;
}
}
357,7 → 356,7
}
block_put(blk);
}
fibril_mutex_unlock(&fat_alloc_lock);
futex_up(&fat_alloc_lock);
 
/*
* We could not find enough clusters. Now we need to free the clusters
/branches/network/uspace/srv/fs/fat/fat.c
89,8 → 89,6
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
return;
case VFS_MOUNTED:
fat_mounted(callid, &call);
break;
109,21 → 107,9
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_CLOSE:
fat_close(callid, &call);
break;
case VFS_DESTROY:
fat_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
fat_open_node(callid, &call);
break;
case VFS_DEVICE:
fat_device(callid, &call);
break;
case VFS_SYNC:
fat_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/network/uspace/srv/fs/fat/Makefile
74,7 → 74,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/devmap/devmap.c
41,7 → 41,7
#include <stdio.h>
#include <errno.h>
#include <bool.h>
#include <fibril_sync.h>
#include <futex.h>
#include <stdlib.h>
#include <string.h>
#include <ipc/devmap.h>
48,71 → 48,60
 
#define NAME "devmap"
 
/** Representation of device driver.
*
* Each driver is responsible for a set of devices.
*
*/
/** Pending lookup structure. */
typedef struct {
/** Pointers to previous and next drivers in linked list */
link_t drivers;
/** Pointer to the linked list of devices controlled by this driver */
link_t devices;
/** Phone asociated with this driver */
ipcarg_t phone;
/** Device driver name */
char *name;
/** Fibril mutex for list of devices owned by this driver */
fibril_mutex_t devices_mutex;
} devmap_driver_t;
link_t link;
char *name; /**< Device name */
ipc_callid_t callid; /**< Call ID waiting for the lookup */
} pending_req_t;
 
/** Info about registered device
*
*/
typedef struct {
/** Pointer to the previous and next device in the list of all devices */
link_t devices;
/** Pointer to the previous and next device in the list of devices
owned by one driver */
link_t driver_devices;
/** Unique device identifier */
dev_handle_t handle;
/** Device name */
char *name;
/** Device driver handling this device */
devmap_driver_t *driver;
} devmap_device_t;
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(drivers_list);
LIST_INITIALIZE(pending_req);
 
/* Locking order:
* drivers_list_mutex
* devices_list_mutex
* (devmap_driver_t *)->devices_mutex
* create_handle_mutex
* drivers_list_futex
* devices_list_futex
* (devmap_driver_t *)->devices_futex
* create_handle_futex
**/
 
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
 
static dev_handle_t last_handle = 0;
 
static dev_handle_t devmap_create_handle(void)
static int devmap_create_handle(void)
{
static int last_handle = 0;
int handle;
/* TODO: allow reusing old handles after their unregistration
* and implement some version of LRU algorithm, avoid overflow
* and implement some version of LRU algorithm
*/
fibril_mutex_lock(&create_handle_mutex);
last_handle++;
fibril_mutex_unlock(&create_handle_mutex);
/* FIXME: overflow */
futex_down(&create_handle_futex);
return last_handle;
last_handle += 1;
handle = last_handle;
futex_up(&create_handle_futex);
return handle;
}
 
 
/** Initialize device mapper.
*
*
*/
static int devmap_init()
{
/* TODO: */
return EOK;
}
 
/** Find device with given name.
*
*/
123,7 → 112,7
while (item != &devices_list) {
device = list_get_instance(item, devmap_device_t, devices);
if (str_cmp(device->name, name) == 0)
if (0 == str_cmp(device->name, name))
break;
item = item->next;
}
140,9 → 129,9
* @todo: use hash table
*
*/
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
static devmap_device_t *devmap_device_find_handle(int handle)
{
fibril_mutex_lock(&devices_list_mutex);
futex_down(&devices_list_futex);
link_t *item = (&devices_list)->next;
devmap_device_t *device = NULL;
155,20 → 144,22
}
if (item == &devices_list) {
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
return NULL;
}
device = list_get_instance(item, devmap_device_t, devices);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
return device;
}
 
/**
*
* Unregister device and free it. It's assumed that driver's device list is
* already locked.
*
*/
static int devmap_device_unregister_core(devmap_device_t *device)
{
182,8 → 173,10
}
 
/**
*
* Read info about new driver and add it into linked list of registered
* drivers.
*
*/
static void devmap_driver_register(devmap_driver_t **odriver)
{
237,7 → 230,7
/*
* Send confirmation to sender and get data into buffer.
*/
if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
free(driver->name);
free(driver);
ipc_answer_0(iid, EREFUSED);
246,21 → 239,21
driver->name[name_size] = 0;
/* Initialize mutex for list of devices owned by this driver */
fibril_mutex_initialize(&driver->devices_mutex);
/* Initialize futex for list of devices owned by this driver */
futex_initialize(&(driver->devices_futex), 1);
/*
* Initialize list of asociated devices
*/
list_initialize(&driver->devices);
list_initialize(&(driver->devices));
/*
* Create connection to the driver
* Create connection to the driver
*/
ipc_call_t call;
callid = async_get_call(&call);
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
ipc_answer_0(callid, ENOTSUP);
free(driver->name);
275,7 → 268,7
list_initialize(&(driver->drivers));
fibril_mutex_lock(&drivers_list_mutex);
futex_down(&drivers_list_futex);
/* TODO:
* check that no driver with name equal to driver->name is registered
285,7 → 278,7
* Insert new driver into list of registered drivers
*/
list_append(&(driver->drivers), &drivers_list);
fibril_mutex_unlock(&drivers_list_mutex);
futex_up(&drivers_list_futex);
ipc_answer_0(iid, EOK);
302,18 → 295,18
if (driver == NULL)
return EEXISTS;
fibril_mutex_lock(&drivers_list_mutex);
futex_down(&drivers_list_futex);
if (driver->phone != 0)
ipc_hangup(driver->phone);
ipc_hangup(driver->phone);
/* Remove it from list of drivers */
/* remove it from list of drivers */
list_remove(&(driver->drivers));
/* Unregister all its devices */
fibril_mutex_lock(&devices_list_mutex);
fibril_mutex_lock(&driver->devices_mutex);
/* unregister all its devices */
futex_down(&devices_list_futex);
futex_down(&(driver->devices_futex));
while (!list_empty(&(driver->devices))) {
devmap_device_t *device = list_get_instance(driver->devices.next,
devmap_device_t, driver_devices);
320,12 → 313,12
devmap_device_unregister_core(device);
}
fibril_mutex_unlock(&driver->devices_mutex);
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&drivers_list_mutex);
futex_up(&(driver->devices_futex));
futex_up(&devices_list_futex);
futex_up(&drivers_list_futex);
/* free name and driver */
if (driver->name != NULL)
if (NULL != driver->name)
free(driver->name);
free(driver);
333,6 → 326,30
return EOK;
}
 
 
/** Process pending lookup requests */
static void process_pending_lookup()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
const devmap_device_t *dev = devmap_device_find_name(pr->name);
if (!dev)
continue;
ipc_answer_1(pr->callid, EOK, dev->handle);
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
 
 
/** Register instance of device
*
*/
383,12 → 400,12
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
fibril_mutex_lock(&devices_list_mutex);
futex_down(&devices_list_futex);
/* Check that device with such name is not already registered */
if (NULL != devmap_device_find_name(device->name)) {
printf(NAME ": Device '%s' already registered\n", device->name);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
free(device->name);
free(device);
ipc_answer_0(iid, EEXISTS);
404,15 → 421,16
list_append(&device->devices, &devices_list);
/* Insert device into list of devices that belog to one driver */
fibril_mutex_lock(&device->driver->devices_mutex);
futex_down(&device->driver->devices_futex);
list_append(&device->driver_devices, &device->driver->devices);
fibril_mutex_unlock(&device->driver->devices_mutex);
fibril_condvar_broadcast(&devices_list_cv);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
ipc_answer_1(iid, EOK, device->handle);
process_pending_lookup();
}
 
/**
436,15 → 454,15
/*
* Get handle from request
*/
dev_handle_t handle = IPC_GET_ARG2(*call);
int handle = IPC_GET_ARG2(*call);
devmap_device_t *dev = devmap_device_find_handle(handle);
if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
if (NULL == dev) {
ipc_answer_0(callid, ENOENT);
return;
}
ipc_forward_fast(callid, dev->driver->phone, dev->handle,
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
}
 
477,7 → 495,7
/*
* Allocate buffer for device name.
*/
char *name = (char *) malloc(size + 1);
char *name = (char *) malloc(size);
if (name == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
495,14 → 513,10
}
name[size] = '\0';
fibril_mutex_lock(&devices_list_mutex);
const devmap_device_t *dev;
recheck:
 
/*
* Find device name in the list of known devices.
* Find device name in linked list of known devices.
*/
dev = devmap_device_find_name(name);
const devmap_device_t *dev = devmap_device_find_name(name);
/*
* Device was not found.
509,18 → 523,24
*/
if (dev == NULL) {
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
/* Blocking lookup */
fibril_condvar_wait(&devices_list_cv,
&devices_list_mutex);
goto recheck;
/* Blocking lookup, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(iid, ENOMEM);
free(name);
return;
}
pr->name = name;
pr->callid = iid;
list_append(&pr->link, &pending_req);
return;
}
ipc_answer_0(iid, ENOENT);
free(name);
fibril_mutex_unlock(&devices_list_mutex);
return;
}
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, dev->handle);
free(name);
529,7 → 549,7
/** Find name of device identified by id and send it to caller.
*
*/
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
{
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
559,99 → 579,6
/* TODO: send name in response */
}
 
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
ipc_answer_1(iid, EOK, list_count(&devices_list));
fibril_mutex_unlock(&devices_list_mutex);
}
 
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EREFUSED);
ipc_answer_0(iid, EREFUSED);
return;
}
if ((size % sizeof(dev_desc_t)) != 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(iid, EREFUSED);
return;
}
size_t count = size / sizeof(dev_desc_t);
dev_desc_t *desc = (dev_desc_t *) malloc(size);
if (desc == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
return;
}
size_t pos = 0;
link_t *item = devices_list.next;
while ((item != &devices_list) && (pos < count)) {
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
desc[pos].handle = device->handle;
str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
pos++;
item = item->next;
}
ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
if (retval != EOK) {
ipc_answer_0(iid, EREFUSED);
free(desc);
return;
}
free(desc);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, pos);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init(void)
{
/* Create NULL device entry */
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL)
return false;
device->name = str_dup("null");
if (device->name == NULL) {
free(device);
return false;
}
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
fibril_mutex_lock(&devices_list_mutex);
/* Get unique device handle */
device->handle = devmap_create_handle();
device->driver = NULL;
/* Insert device into list of all devices */
list_append(&device->devices, &devices_list);
fibril_mutex_unlock(&devices_list_mutex);
return true;
}
 
/** Handle connection with device driver.
*
*/
660,7 → 587,7
/* Accept connection */
ipc_answer_0(iid, EOK);
devmap_driver_t *driver = NULL;
devmap_driver_t *driver = NULL;
devmap_driver_register(&driver);
if (NULL == driver)
674,6 → 601,7
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DRIVER_UNREGISTER:
if (NULL == driver)
693,7 → 621,7
devmap_get_handle(callid, &call);
break;
case DEVMAP_DEVICE_GET_NAME:
devmap_get_name(callid, &call);
devmap_get_handle(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION))
726,19 → 654,15
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DEVICE_GET_HANDLE:
devmap_get_handle(callid, &call);
break;
case DEVMAP_DEVICE_GET_NAME:
/* TODO */
devmap_get_name(callid, &call);
break;
case DEVMAP_DEVICE_GET_COUNT:
devmap_get_count(callid, &call);
break;
case DEVMAP_DEVICE_GET_DEVICES:
devmap_get_devices(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, ENOENT);
765,7 → 689,7
break;
default:
/* No such interface */
ipc_answer_0(iid, ENOENT);
ipc_answer_0(iid, ENOENT);
}
}
 
776,7 → 700,7
{
printf(NAME ": HelenOS Device Mapper\n");
if (!devmap_init()) {
if (devmap_init() != 0) {
printf(NAME ": Error while initializing service\n");
return -1;
}
783,7 → 707,7
/* Set a handler of incomming connections */
async_set_client_connection(devmap_connection);
 
/* Register device mapper at naming service */
ipcarg_t phonead;
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
/branches/network/uspace/srv/devmap/Makefile
34,8 → 34,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
CFLAGS += -I../libipc/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
65,7 → 67,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/vfs/vfs_ops.c
43,8 → 43,9
#include <stdlib.h>
#include <string.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/list.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
54,12 → 55,26
/* Forward declarations of static functions. */
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
 
/** Pending mount structure. */
typedef struct {
link_t link;
char *fs_name; /**< File system name */
char *mp; /**< Mount point */
char *opts; /**< Mount options. */
ipc_callid_t callid; /**< Call ID waiting for the mount */
ipc_callid_t rid; /**< Request ID */
dev_handle_t dev_handle; /**< Device handle */
} pending_req_t;
 
LIST_INITIALIZE(pending_req);
 
/**
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a
* concurrent VFS operation which modifies the file system namespace.
*/
FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
RWLOCK_INITIALIZE(namespace_rwlock);
 
futex_t rootfs_futex = FUTEX_INITIALIZER;
vfs_pair_t rootfs = {
.fs_handle = 0,
.dev_handle = 0
69,24 → 84,21
fs_handle_t fs_handle, char *mp, char *opts)
{
vfs_lookup_res_t mp_res;
vfs_lookup_res_t mr_res;
vfs_node_t *mp_node = NULL;
vfs_node_t *mr_node;
fs_index_t rindex;
size_t rsize;
unsigned rlnkcnt;
ipcarg_t rc;
int phone;
aid_t msg;
ipc_call_t answer;
 
/* Resolve the path to the mountpoint. */
fibril_rwlock_write_lock(&namespace_rwlock);
futex_down(&rootfs_futex);
if (rootfs.fs_handle) {
/* We already have the root FS. */
rwlock_write_lock(&namespace_rwlock);
if (str_cmp(mp, "/") == 0) {
/* Trying to mount root FS over root FS */
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, EBUSY);
return;
}
94,7 → 106,8
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
if (rc != EOK) {
/* The lookup failed for some reason. */
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
101,7 → 114,8
mp_node = vfs_node_get(&mp_res);
if (!mp_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, ENOMEM);
return;
}
111,9 → 125,16
* It will be dropped upon the corresponding VFS_UNMOUNT.
* This prevents the mount point from being deleted.
*/
rwlock_write_unlock(&namespace_rwlock);
} else {
/* We still don't have the root file system mounted. */
if (str_cmp(mp, "/") == 0) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
fs_index_t rindex;
size_t rsize;
unsigned rlnkcnt;
/*
* For this simple, but important case,
* we are almost done.
129,7 → 150,7
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
137,7 → 158,7
vfs_release_phone(phone);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
155,12 → 176,12
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
futex_up(&rootfs_futex);
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
} else {
168,11 → 189,12
* We can't resolve this without the root filesystem
* being mounted first.
*/
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, ENOENT);
return;
}
}
futex_up(&rootfs_futex);
/*
* At this point, we have all necessary pieces: file system and device
179,9 → 201,6
* handles, and we know the mount point VFS node.
*/
int mountee_phone = vfs_grab_phone(fs_handle);
assert(mountee_phone >= 0);
 
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
msg = async_send_4(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
188,23 → 207,6
(ipcarg_t) mp_res.triplet.index,
(ipcarg_t) fs_handle,
(ipcarg_t) dev_handle, &answer);
/* send connection */
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(mountee_phone);
vfs_release_phone(phone);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
ipc_answer_0(rid, rc);
fibril_rwlock_write_unlock(&namespace_rwlock);
return;
}
 
vfs_release_phone(mountee_phone);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
if (rc != EOK) {
213,7 → 215,6
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
220,31 → 221,44
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
rindex = (fs_index_t) IPC_GET_ARG1(answer);
rsize = (size_t) IPC_GET_ARG2(answer);
rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = rindex;
mr_res.size = rsize;
mr_res.lnkcnt = rlnkcnt;
mr_res.type = VFS_NODE_DIRECTORY;
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
} else {
if (rc != EOK) {
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
}
 
ipc_answer_0(rid, rc);
fibril_rwlock_write_unlock(&namespace_rwlock);
}
 
/** Process pending mount requests */
void vfs_process_pending_mount()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
if (!fs_handle)
continue;
/* Acknowledge that we know fs_name. */
ipc_answer_0(pr->callid, EOK);
/* Do the mount */
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp,
pr->opts);
free(pr->fs_name);
free(pr->mp);
free(pr->opts);
list_remove(cur);
free(pr);
goto loop;
}
}
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
/*
398,17 → 412,33
* Check if we know a file system with the same name as is in fs_name.
* This will also give us its file system handle.
*/
fibril_mutex_lock(&fs_head_lock);
fs_handle_t fs_handle;
recheck:
fs_handle = fs_name_to_handle(fs_name, false);
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
if (flags & IPC_FLAG_BLOCKING) {
fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
goto recheck;
pending_req_t *pr;
 
/* Blocking mount, add to pending list */
pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(mp);
free(fs_name);
free(opts);
return;
}
pr->fs_name = fs_name;
pr->mp = mp;
pr->opts = opts;
pr->callid = callid;
pr->rid = rid;
pr->dev_handle = dev_handle;
link_initialize(&pr->link);
list_append(&pr->link, &pending_req);
return;
}
fibril_mutex_unlock(&fs_head_lock);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
free(mp);
416,7 → 446,6
free(opts);
return;
}
fibril_mutex_unlock(&fs_head_lock);
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
434,7 → 463,7
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* The POSIX interface is open(path, oflag, mode).
* We can receive oflags and mode along with the VFS_OPEN call; the path
447,30 → 476,29
int oflag = IPC_GET_ARG2(*request);
int mode = IPC_GET_ARG3(*request);
size_t len;
 
/*
* 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.
* L_DIRECTORY.
*/
if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
((lflag & L_OPEN) != 0)) {
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
ipc_answer_0(rid, EINVAL);
return;
}
 
if (oflag & O_CREAT)
lflag |= L_CREATE;
if (oflag & O_EXCL)
lflag |= L_EXCLUSIVE;
 
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);
477,7 → 505,6
ipc_answer_0(rid, ENOMEM);
return;
}
int rc;
if ((rc = ipc_data_write_finalize(callid, path, len))) {
ipc_answer_0(rid, rc);
492,40 → 519,40
* triplet.
*/
if (lflag & L_CREATE)
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
else
fibril_rwlock_read_lock(&namespace_rwlock);
rwlock_read_lock(&namespace_rwlock);
 
/* The path is now populated and we can call vfs_lookup_internal(). */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
if (rc != EOK) {
rc = vfs_lookup_internal(path, lflag, &lr, NULL);
if (rc) {
if (lflag & L_CREATE)
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
else
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(path);
return;
}
 
/* Path is no longer needed. */
free(path);
 
vfs_node_t *node = vfs_node_get(&lr);
if (lflag & L_CREATE)
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
else
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
 
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
fibril_rwlock_write_lock(&node->contents_rwlock);
rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
fibril_rwlock_write_unlock(&node->contents_rwlock);
rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
532,9 → 559,9
}
node->size = 0;
}
fibril_rwlock_write_unlock(&node->contents_rwlock);
rwlock_write_unlock(&node->contents_rwlock);
}
 
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
547,9 → 574,9
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
if (oflag & O_APPEND)
file->append = true;
 
/*
* The following increase in reference count is for the fact that the
* file is being opened and that a file structure is pointing to it.
559,210 → 586,18
*/
vfs_node_addref(node);
vfs_node_put(node);
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
// FIXME: check for sanity of the supplied fs, dev and index
if (!vfs_files_init()) {
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* The interface is open_node(fs, dev, index, oflag).
*/
vfs_lookup_res_t lr;
lr.triplet.fs_handle = IPC_GET_ARG1(*request);
lr.triplet.dev_handle = IPC_GET_ARG2(*request);
lr.triplet.index = IPC_GET_ARG3(*request);
int oflag = IPC_GET_ARG4(*request);
fibril_rwlock_read_lock(&namespace_rwlock);
int rc = vfs_open_node_internal(&lr);
if (rc != EOK) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
vfs_node_t *node = vfs_node_get(&lr);
fibril_rwlock_read_unlock(&namespace_rwlock);
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
fibril_rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
fibril_rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
}
node->size = 0;
}
fibril_rwlock_write_unlock(&node->contents_rwlock);
}
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
*/
int fd = vfs_fd_alloc();
if (fd < 0) {
vfs_node_put(node);
ipc_answer_0(rid, fd);
return;
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
file->append = true;
/*
* The following increase in reference count is for the fact that the
* 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.
*/
vfs_node_addref(node);
vfs_node_put(node);
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_node(ipc_callid_t rid, ipc_call_t *request)
void vfs_close(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);
/* 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_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);
 
/* 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);
int rc = vfs_fd_free(fd);
ipc_answer_0(rid, rc);
}
 
void vfs_close(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_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);
 
/* 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);
int retval = IPC_GET_ARG1(answer);
if (retval != EOK)
ipc_answer_0(rid, retval);
retval = vfs_fd_free(fd);
ipc_answer_0(rid, retval);
}
 
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
{
 
805,7 → 640,7
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
812,9 → 647,9
* the same time.
*/
if (read)
fibril_rwlock_read_lock(&file->node->contents_rwlock);
rwlock_read_lock(&file->node->contents_rwlock);
else
fibril_rwlock_write_lock(&file->node->contents_rwlock);
rwlock_write_lock(&file->node->contents_rwlock);
 
if (file->node->type == VFS_NODE_DIRECTORY) {
/*
822,7 → 657,7
* while we are in readdir().
*/
assert(read);
fibril_rwlock_read_lock(&namespace_rwlock);
rwlock_read_lock(&namespace_rwlock);
}
int fs_phone = vfs_grab_phone(file->node->fs_handle);
842,32 → 677,31
* don't have to bother.
*/
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
/* Unlock the VFS node. */
if (read)
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
rwlock_read_unlock(&file->node->contents_rwlock);
else {
/* Update the cached version of node's size. */
if (rc == EOK)
file->node->size = IPC_GET_ARG2(answer);
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
rwlock_write_unlock(&file->node->contents_rwlock);
}
/* Update the position pointer and unlock the open file. */
if (rc == EOK)
file->pos += bytes;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
/*
* FS server's reply is the final result of the whole operation we
901,40 → 735,40
}
 
off_t newpos;
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
if (whence == SEEK_SET) {
file->pos = off;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, off);
return;
}
if (whence == SEEK_CUR) {
if (file->pos + off < file->pos) {
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
file->pos += off;
newpos = file->pos;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
if (whence == SEEK_END) {
fibril_rwlock_read_lock(&file->node->contents_rwlock);
rwlock_read_lock(&file->node->contents_rwlock);
size_t size = file->node->size;
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
rwlock_read_unlock(&file->node->contents_rwlock);
if (size + off < size) {
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
newpos = size + off;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EINVAL);
}
 
963,16 → 797,16
ipc_answer_0(rid, ENOENT);
return;
}
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
 
fibril_rwlock_write_lock(&file->node->contents_rwlock);
rwlock_write_lock(&file->node->contents_rwlock);
rc = vfs_truncate_internal(file->node->fs_handle,
file->node->dev_handle, file->node->index, size);
if (rc == EOK)
file->node->size = size;
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
rwlock_write_unlock(&file->node->contents_rwlock);
 
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, (ipcarg_t)rc);
}
 
1002,10 → 836,10
}
path[len] = '\0';
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
rc = vfs_lookup_internal(path, lflag, NULL, NULL);
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
free(path);
ipc_answer_0(rid, rc);
}
1036,13 → 870,13
}
path[len] = '\0';
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
lflag &= L_DIRECTORY; /* sanitize lflag */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
free(path);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
1053,10 → 887,10
* VFS_DESTROY'ed after the last reference to it is dropped.
*/
vfs_node_t *node = vfs_node_get(&lr);
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, EOK);
}
1118,16 → 952,8
}
oldc[olen] = '\0';
newc[nlen] = '\0';
if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
((newc[str_length(oldc)] == '/') ||
(str_length(oldc) == 1) ||
(str_length(oldc) == str_length(newc)))) {
/*
* oldc is a prefix of newc and either
* - newc continues with a / where oldc ends, or
* - oldc was / itself, or
* - oldc and newc are equal.
*/
if (!str_lcmp(newc, oldc, str_length(oldc))) {
/* oldc is a prefix of newc */
ipc_answer_0(rid, EINVAL);
free(old);
free(new);
1137,11 → 963,11
vfs_lookup_res_t old_lr;
vfs_lookup_res_t new_lr;
vfs_lookup_res_t new_par_lr;
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
/* Lookup the node belonging to the old file name. */
rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1149,31 → 975,16
}
vfs_node_t *old_node = vfs_node_get(&old_lr);
if (!old_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
return;
}
/* Determine the path to the parent of the node with the new name. */
char *parentc = str_dup(newc);
if (!parentc) {
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
return;
}
char *lastsl = str_rchr(parentc + 1, '/');
if (lastsl)
*lastsl = '\0';
else
parentc[1] = '\0';
/* Lookup parent of the new file name. */
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
free(parentc); /* not needed anymore */
rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1182,7 → 993,7
/* Check whether linking to the same file system instance. */
if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
(old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, EXDEV); /* different file systems */
free(old);
free(new);
1198,18 → 1009,18
case EOK:
new_node = vfs_node_get(&new_lr);
if (!new_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
new_node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
break;
default:
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOTEMPTY);
free(old);
free(new);
1218,7 → 1029,7
/* Create the new link for the new name. */
rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
if (new_node)
vfs_node_put(new_node);
ipc_answer_0(rid, rc);
1226,13 → 1037,13
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
old_node->lnkcnt++;
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
/* Destroy the link for the old name. */
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1241,10 → 1052,10
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
old_node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1255,4 → 1066,4
 
/**
* @}
*/
*/
/branches/network/uspace/srv/vfs/vfs_register.c
45,16 → 45,15
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <libadt/list.h>
#include <as.h>
#include <assert.h>
#include <atomic.h>
#include "vfs.h"
 
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
LIST_INITIALIZE(fs_head);
atomic_t fs_head_futex = FUTEX_INITIALIZER;
link_t fs_head;
 
atomic_t fs_handle_next = {
.count = 1
160,7 → 159,7
return;
}
link_initialize(&fs_info->fs_link);
fibril_mutex_initialize(&fs_info->phone_lock);
futex_initialize(&fs_info->phone_futex, 1);
rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size);
if (rc != EOK) {
181,7 → 180,8
return;
}
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
fibril_inc_sercount();
 
/*
* Check for duplicit registrations.
191,7 → 191,8
* We already register a fs like this.
*/
dprintf("FS is already registered.\n");
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
free(fs_info);
ipc_answer_0(callid, EEXISTS);
ipc_answer_0(rid, EEXISTS);
213,7 → 214,8
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
free(fs_info);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
231,7 → 233,8
if (!ipc_share_in_receive(&callid, &size)) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
245,7 → 248,8
if (size != PLB_SIZE) {
dprintf("Client suggests wrong size of PFB, size = %d\n", size);
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
269,11 → 273,16
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle);
fibril_condvar_broadcast(&fs_head_cv);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
/* Process pending mount requests possibly waiting
* for this filesystem implementation.
*/
vfs_process_pending_mount();
}
 
/** For a given file system handle, implement policy for allocating a phone.
285,49 → 294,76
*/
int vfs_grab_phone(fs_handle_t handle)
{
int phone;
 
/*
* For now, we don't try to be very clever and very fast. We simply
* lookup the phone in the fs_head list and duplicate it. The duplicate
* phone will be returned to the client and the client will use it for
* communication. In the future, we should cache the connections so
* that they do not have to be reestablished over and over again.
* For now, we don't try to be very clever and very fast.
* We simply lookup the phone in the fs_head list. We currently don't
* open any additional phones (even though that itself would be pretty
* straightforward; housekeeping multiple open phones to a FS task would
* be more demanding). Instead, we simply take the respective
* phone_futex and keep it until vfs_release_phone().
*/
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
link_t *cur;
fs_info_t *fs;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->fs_handle == handle) {
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_lock(&fs->phone_lock);
phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
fibril_mutex_unlock(&fs->phone_lock);
 
assert(phone > 0);
return phone;
futex_up(&fs_head_futex);
/*
* For now, take the futex unconditionally.
* Oh yeah, serialization rocks.
* It will be up'ed in vfs_release_phone().
*/
futex_down(&fs->phone_futex);
/*
* Avoid deadlock with other fibrils in the same thread
* by disabling fibril preemption.
*/
fibril_inc_sercount();
return fs->phone;
}
}
fibril_mutex_unlock(&fs_head_lock);
futex_up(&fs_head_futex);
return 0;
}
 
/** Tell VFS that the phone is not needed anymore.
/** Tell VFS that the phone is in use for any request.
*
* @param phone Phone to FS task.
*/
void vfs_release_phone(int phone)
{
/* TODO: implement connection caching */
ipc_hangup(phone);
bool found = false;
 
/*
* Undo the fibril_inc_sercount() done in vfs_grab_phone().
*/
fibril_dec_sercount();
futex_down(&fs_head_futex);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->phone == phone) {
found = true;
futex_up(&fs_head_futex);
futex_up(&fs->phone_futex);
return;
}
}
futex_up(&fs_head_futex);
 
/*
* Not good to get here.
*/
assert(found == true);
}
 
/** Convert file system name to its handle.
*
* @param name File system name.
* @param lock If true, the function will lock and unlock the
* fs_head_lock.
* @param lock If true, the function will down and up the
* fs_head_futex.
*
* @return File system handle or zero if file system not found.
*/
336,7 → 372,7
int handle = 0;
if (lock)
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
346,7 → 382,7
}
}
if (lock)
fibril_mutex_unlock(&fs_head_lock);
futex_up(&fs_head_futex);
return handle;
}
 
/branches/network/uspace/srv/vfs/vfs.h
28,25 → 28,70
 
/** @addtogroup fs
* @{
*/
*/
 
#ifndef VFS_VFS_H_
#define VFS_VFS_H_
 
#include <ipc/ipc.h>
#include <adt/list.h>
#include <fibril_sync.h>
#include <libadt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <sys/types.h>
#include <devmap.h>
#include <bool.h>
#include <ipc/vfs.h>
 
// FIXME: according to CONFIG_DEBUG
// #define dprintf(...) printf(__VA_ARGS__)
// #define dprintf(...) printf(__VA_ARGS__)
 
#define dprintf(...)
 
#define VFS_FIRST IPC_FIRST_USER_METHOD
 
/* Basic types. */
typedef int16_t fs_handle_t;
typedef int16_t dev_handle_t;
typedef uint32_t fs_index_t;
 
typedef enum {
VFS_READ = VFS_FIRST,
VFS_WRITE,
VFS_TRUNCATE,
VFS_MOUNT,
VFS_UNMOUNT,
VFS_LAST_CMN, /* keep this the last member of this enum */
} vfs_request_cmn_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;
 
typedef enum {
VFS_REGISTER = VFS_LAST_CMN,
VFS_OPEN,
VFS_CLOSE,
VFS_SEEK,
VFS_MKDIR,
VFS_UNLINK,
VFS_RENAME,
VFS_LAST_SRV, /* keep this the last member of this enum */
} vfs_request_srv_t;
 
#define FS_NAME_MAXLEN 20
 
/**
* A structure like this is passed to VFS by each individual FS upon its
* registration. It assosiates a human-readable identifier with each
* registered FS.
*/
typedef struct {
/** Unique identifier of the fs. */
char name[FS_NAME_MAXLEN + 1];
} vfs_info_t;
 
/**
* A structure like this will be allocated for each registered file system.
*/
typedef struct {
53,7 → 98,7
link_t fs_link;
vfs_info_t vfs_info;
fs_handle_t fs_handle;
fibril_mutex_t phone_lock;
futex_t phone_futex; /**< Phone serializing futex. */
ipcarg_t phone;
} fs_info_t;
 
60,8 → 105,8
/**
* VFS_PAIR uniquely represents a file system instance.
*/
#define VFS_PAIR \
fs_handle_t fs_handle; \
#define VFS_PAIR \
fs_handle_t fs_handle; \
dev_handle_t dev_handle;
 
/**
71,8 → 116,8
* @note fs_handle, dev_handle and index are meant to be returned in one
* IPC reply.
*/
#define VFS_TRIPLET \
VFS_PAIR; \
#define VFS_TRIPLET \
VFS_PAIR; \
fs_index_t index;
 
typedef struct {
83,6 → 128,50
VFS_TRIPLET;
} vfs_triplet_t;
 
/*
* Lookup flags.
*/
/**
* No lookup flags used.
*/
#define L_NONE 0
/**
* Lookup will succeed only if the object is a regular file. If L_CREATE is
* specified, an empty file will be created. This flag is mutually exclusive
* with L_DIRECTORY.
*/
#define L_FILE 1
/**
* Lookup wil succeed only if the object is a directory. If L_CREATE is
* specified, an empty directory will be created. This flag is mutually
* exclusive with L_FILE.
*/
#define L_DIRECTORY 2
/**
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
*/
#define L_EXCLUSIVE 4
/**
* L_CREATE is used for creating both regular files and directories.
*/
#define L_CREATE 8
/**
* L_LINK is used for linking to an already existing nodes.
*/
#define L_LINK 16
/**
* L_UNLINK is used to remove leaves from the file system namespace. This flag
* cannot be passed directly by the client, but will be set by VFS during
* VFS_UNLINK.
*/
#define L_UNLINK 32
/**
* L_PARENT performs a lookup but returns the triplet of the parent node.
* This flag may not be combined with any other lookup flag.
*/
#define L_PARENT 64
 
typedef enum vfs_node_type {
VFS_NODE_UNKNOWN,
VFS_NODE_FILE,
121,7 → 210,7
/**
* Holding this rwlock prevents modifications of the node's contents.
*/
fibril_rwlock_t contents_rwlock;
rwlock_t contents_rwlock;
} vfs_node_t;
 
/**
130,7 → 219,7
*/
typedef struct {
/** Serializes access to this open file. */
fibril_mutex_t lock;
futex_t lock;
 
vfs_node_t *node;
144,14 → 233,16
off_t pos;
} vfs_file_t;
 
extern fibril_mutex_t nodes_mutex;
extern futex_t nodes_futex;
 
extern fibril_condvar_t fs_head_cv;
extern fibril_mutex_t fs_head_lock;
extern link_t fs_head; /**< List of registered file systems. */
 
extern vfs_pair_t rootfs; /**< Root file system. */
 
#define MAX_PATH_LEN (64 * 1024)
 
#define PLB_SIZE (2 * MAX_PATH_LEN)
 
/** Each instance of this type describes one path lookup in progress. */
typedef struct {
link_t plb_link; /**< Active PLB entries list link. */
159,7 → 250,7
size_t len; /**< Number of characters in this PLB entry. */
} plb_entry_t;
 
extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */
extern uint8_t *plb; /**< Path Lookup Buffer */
extern link_t plb_head; /**< List of active PLB entries. */
 
166,7 → 257,7
#define MAX_MNTOPTS_LEN 256
 
/** Holding this rwlock prevents changes in file system namespace. */
extern fibril_rwlock_t namespace_rwlock;
extern rwlock_t namespace_rwlock;
 
extern int vfs_grab_phone(fs_handle_t);
extern void vfs_release_phone(int);
173,9 → 264,8
 
extern fs_handle_t fs_name_to_handle(char *, bool);
 
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
vfs_pair_t *, ...);
extern int vfs_open_node_internal(vfs_lookup_res_t *);
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *,
...);
 
extern bool vfs_nodes_init(void);
extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *);
194,13 → 284,10
extern void vfs_node_addref(vfs_node_t *);
extern void vfs_node_delref(vfs_node_t *);
 
extern void vfs_process_pending_mount(void);
extern void vfs_register(ipc_callid_t, ipc_call_t *);
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 *);
/branches/network/uspace/srv/vfs/vfs.c
43,6 → 43,7
#include <bool.h>
#include <string.h>
#include <as.h>
#include <libadt/list.h>
#include <atomic.h>
#include "vfs.h"
 
51,7 → 52,7
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = true;
 
/*
* The connection was opened via the IPC_CONNECT_ME_TO call.
* This call needs to be answered.
79,9 → 80,28
case IPC_M_PHONE_HUNGUP:
keep_on_going = false;
break;
case IPC_M_CONNECT_ME_TO:
/*
* Connect the client file system to another one.
*/
/* FIXME:
* Prevent ordinary clients from connecting to file
* system servers directly. This should be solved by
* applying some security mechanisms.
*/
fs_handle = IPC_GET_ARG1(call);
phone = vfs_grab_phone(fs_handle);
(void) ipc_forward_fast(callid, phone, 0, 0, 0,
IPC_FF_NONE);
vfs_release_phone(phone);
break;
case VFS_REGISTER:
vfs_register(callid, &call);
keep_on_going = false;
/*
* Keep the connection open so that a file system can
* later ask us to connect it to another file system.
* This is necessary to support non-root mounts.
*/
break;
case VFS_MOUNT:
vfs_mount(callid, &call);
89,9 → 109,6
case VFS_OPEN:
vfs_open(callid, &call);
break;
case VFS_OPEN_NODE:
vfs_open_node(callid, &call);
break;
case VFS_CLOSE:
vfs_close(callid, &call);
break;
116,15 → 133,6
case VFS_RENAME:
vfs_rename(callid, &call);
break;
case VFS_DEVICE:
vfs_device(callid, &call);
break;
case VFS_SYNC:
vfs_sync(callid, &call);
break;
case VFS_NODE:
vfs_node(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
139,6 → 147,11
printf(NAME ": HelenOS VFS server\n");
/*
* Initialize the list of registered file systems.
*/
list_initialize(&fs_head);
/*
* Initialize VFS node hash table.
*/
if (!vfs_nodes_init()) {
149,6 → 162,7
/*
* Allocate and initialize the Path Lookup Buffer.
*/
list_initialize(&plb_head);
plb = as_get_mappable_page(PLB_SIZE);
if (!plb) {
printf(NAME ": Cannot allocate a mappable piece of address space\n");
163,10 → 177,10
memset(plb, 0, PLB_SIZE);
/*
* Set a connection handling function/fibril.
* Set a connectio handling function/fibril.
*/
async_set_client_connection(vfs_connection);
 
/*
* Register at the naming service.
*/
/branches/network/uspace/srv/vfs/vfs_node.c
38,14 → 38,15
#include "vfs.h"
#include <stdlib.h>
#include <string.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <assert.h>
#include <async.h>
#include <errno.h>
 
/** Mutex protecting the VFS node hash table. */
FIBRIL_MUTEX_INITIALIZE(nodes_mutex);
/** Futex protecting the VFS node hash table. */
futex_t nodes_futex = FUTEX_INITIALIZER;
 
#define NODES_BUCKETS_LOG 8
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG)
88,9 → 89,9
*/
void vfs_node_addref(vfs_node_t *node)
{
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
_vfs_node_addref(node);
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
}
 
/** Decrement reference count of a VFS node.
104,7 → 105,7
bool free_vfs_node = false;
bool free_fs_node = false;
 
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
if (node->refcnt-- == 1) {
/*
* We are dropping the last reference to this node.
120,7 → 121,7
if (!node->lnkcnt)
free_fs_node = true;
}
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
 
if (free_fs_node) {
/*
160,12 → 161,12
link_t *tmp;
vfs_node_t *node;
 
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
tmp = hash_table_find(&nodes, key);
if (!tmp) {
node = (vfs_node_t *) malloc(sizeof(vfs_node_t));
if (!node) {
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
return NULL;
}
memset(node, 0, sizeof(vfs_node_t));
176,10 → 177,10
node->lnkcnt = result->lnkcnt;
node->type = result->type;
link_initialize(&node->nh_link);
fibril_rwlock_initialize(&node->contents_rwlock);
rwlock_initialize(&node->contents_rwlock);
hash_table_insert(&nodes, key, &node->nh_link);
} else {
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
if (node->type == VFS_NODE_UNKNOWN &&
result->type != VFS_NODE_UNKNOWN) {
/* Upgrade the node type. */
192,7 → 193,7
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN);
 
_vfs_node_addref(node);
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
 
return node;
}
232,4 → 233,4
 
/**
* @}
*/
*/
/branches/network/uspace/srv/vfs/vfs_lookup.c
28,10 → 28,10
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs_lookup.c
* @file vfs_lookup.c
* @brief
*/
 
42,28 → 42,27
#include <string.h>
#include <stdarg.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <libadt/list.h>
#include <vfs/canonify.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
 
FIBRIL_MUTEX_INITIALIZE(plb_mutex);
LIST_INITIALIZE(plb_head); /**< PLB entry ring buffer. */
futex_t plb_futex = FUTEX_INITIALIZER;
link_t plb_head; /**< PLB entry ring buffer. */
uint8_t *plb = NULL;
 
/** Perform a path lookup.
*
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
*
* @return EOK on success or an error code from errno.h.
*
* @return EOK on success or an error code from errno.h.
*/
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
vfs_pair_t *altroot, ...)
92,7 → 91,7
va_end(ap);
}
fibril_mutex_lock(&plb_mutex);
futex_down(&plb_futex);
 
plb_entry_t entry;
link_initialize(&entry.plb_link);
119,7 → 118,7
/*
* The buffer cannot absorb the path.
*/
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
return ELIMIT;
}
} else {
127,7 → 126,7
/*
* The buffer cannot absorb the path.
*/
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
return ELIMIT;
}
}
146,7 → 145,7
*/
list_append(&entry.plb_link, &plb_head);
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
 
/*
* Copy the path into PLB.
163,12 → 162,12
(ipcarg_t) (first + len - 1) % PLB_SIZE,
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index,
&answer);
vfs_release_phone(phone);
 
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
fibril_mutex_lock(&plb_mutex);
 
futex_down(&plb_futex);
list_remove(&entry.plb_link);
/*
* Erasing the path from PLB will come handy for debugging purposes.
175,9 → 174,9
*/
memset(&plb[first], 0, cnt1);
memset(plb, 0, cnt2);
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
 
if ((rc == EOK) && (result)) {
if ((rc == EOK) && result) {
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer);
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
194,39 → 193,6
return rc;
}
 
/** Perform a node open operation.
*
* @return EOK on success or an error code from errno.h.
*
*/
int vfs_open_node_internal(vfs_lookup_res_t *result)
{
int phone = vfs_grab_phone(result->triplet.fs_handle);
ipc_call_t answer;
aid_t req = async_send_2(phone, VFS_OPEN_NODE,
(ipcarg_t) result->triplet.dev_handle,
(ipcarg_t) result->triplet.index, &answer);
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
result->size = (size_t) IPC_GET_ARG1(answer);
result->lnkcnt = (unsigned) IPC_GET_ARG2(answer);
if (IPC_GET_ARG3(answer) & L_FILE)
result->type = VFS_NODE_FILE;
else if (IPC_GET_ARG3(answer) & L_DIRECTORY)
result->type = VFS_NODE_DIRECTORY;
else
result->type = VFS_NODE_UNKNOWN;
}
return rc;
}
 
/**
* @}
*/
/branches/network/uspace/srv/vfs/Makefile
69,7 → 69,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/vfs/vfs_file.c
40,8 → 40,6
#include <string.h>
#include <assert.h>
#include <bool.h>
#include <fibril.h>
#include <fibril_sync.h>
#include "vfs.h"
 
/**
57,9 → 55,9
* first VFS_OPEN operation.
*
* This resource being per-connection and, in the first place, per-fibril, we
* don't need to protect it by a mutex.
* don't need to protect it by a futex.
*/
fibril_local vfs_file_t **files = NULL;
__thread vfs_file_t **files = NULL;
 
/** Initialize the table of open files. */
bool vfs_files_init(void)
80,23 → 78,19
*/
int vfs_fd_alloc(void)
{
if (!vfs_files_init())
return ENOMEM;
unsigned int i;
int i;
 
for (i = 0; i < MAX_OPEN_FILES; i++) {
if (!files[i]) {
files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
if (!files[i])
return ENOMEM;
memset(files[i], 0, sizeof(vfs_file_t));
fibril_mutex_initialize(&files[i]->lock);
futex_initialize(&files[i]->lock, 1);
vfs_file_addref(files[i]);
return (int) i;
return i;
}
}
return EMFILE;
}
 
109,15 → 103,10
*/
int vfs_fd_free(int fd)
{
if (!vfs_files_init())
return ENOMEM;
if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
return EBADF;
vfs_file_delref(files[fd]);
files[fd] = NULL;
return EOK;
}
 
161,15 → 150,11
*/
vfs_file_t *vfs_file_get(int fd)
{
if (!vfs_files_init())
return NULL;
if ((fd >= 0) && (fd < MAX_OPEN_FILES))
if (fd < MAX_OPEN_FILES)
return files[fd];
return NULL;
}
 
/**
* @}
*/
*/
/branches/network/uspace/srv/ns/clonable.c
File deleted
/branches/network/uspace/srv/ns/task.h
File deleted
/branches/network/uspace/srv/ns/ns.h
File deleted
/branches/network/uspace/srv/ns/clonable.h
File deleted
/branches/network/uspace/srv/ns/service.c
File deleted
/branches/network/uspace/srv/ns/task.c
File deleted
/branches/network/uspace/srv/ns/service.h
File deleted
/branches/network/uspace/srv/ns/ns.c
35,28 → 35,93
* @brief Naming service for HelenOS IPC.
*/
 
 
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <stdio.h>
#include <bool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
#include <sysinfo.h>
#include <loader/loader.h>
#include <ddi.h>
#include <as.h>
#include <ddi.h>
#include <event.h>
#include <macros.h>
#include <sysinfo.h>
#include "ns.h"
#include "service.h"
#include "clonable.h"
#include "task.h"
 
#define NAME "ns"
 
#define NS_HASH_TABLE_CHAINS 20
 
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
static void connect_to_service(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid);
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
 
/* Static functions implementing NS hash table operations. */
static hash_index_t ns_hash(unsigned long *key);
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
static void ns_remove(link_t *item);
 
/** Operations for NS hash table. */
static hash_table_operations_t ns_hash_table_ops = {
.hash = ns_hash,
.compare = ns_compare,
.remove_callback = ns_remove
};
 
/** NS hash table structure. */
static hash_table_t ns_hash_table;
 
/** NS hash table item. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
} hashed_service_t;
 
/** Pending connection structure. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
ipcarg_t arg2; /**< Second argument */
ipcarg_t arg3; /**< Third argument */
} pending_req_t;
 
static link_t pending_req;
 
/** Request for connection to a clonable service. */
typedef struct {
link_t link;
ipcarg_t service;
ipc_call_t call;
ipc_callid_t callid;
} cs_req_t;
 
/** List of clonable-service connection requests. */
static link_t cs_req;
 
static void *clockaddr = NULL;
static void *klogaddr = NULL;
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr,
size_t pages, void **addr)
/** Return true if @a service is clonable. */
static bool service_clonable(int service)
{
return (service == SERVICE_LOAD);
}
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, count_t pages, void **addr)
{
if (ph_addr == NULL) {
ipc_answer_0(callid, ENOENT);
return;
80,53 → 145,67
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ);
}
 
/** Process pending connection requests */
static void process_pending_req()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
unsigned long keys[3] = {
pr->service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link)
continue;
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
pr->arg2, pr->arg3, 0, IPC_FF_NONE);
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, retval);
list_remove(cur);
free(pr);
goto loop;
}
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS IPC Naming Service\n");
int rc = service_init();
if (rc != EOK)
return rc;
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
&ns_hash_table_ops)) {
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
rc = clonable_init();
if (rc != EOK)
return rc;
list_initialize(&pending_req);
list_initialize(&cs_req);
rc = task_init();
if (rc != EOK)
return rc;
printf(NAME ": Accepting connections\n");
while (true) {
process_pending_conn();
process_pending_wait();
process_pending_req();
ipc_call_t call;
ipc_callid_t callid = ipc_wait_for_call(&call);
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)) {
case SERVICE_MEM_REALTIME:
get_as_area(callid, &call,
(void *) sysinfo_value("clock.faddr"),
1, &clockaddr);
get_as_area(callid, &call, sysinfo_value("clock.faddr"), 1, &clockaddr);
break;
case SERVICE_MEM_KLOG:
get_as_area(callid, &call,
(void *) sysinfo_value("klog.faddr"),
sysinfo_value("klog.pages"), &klogaddr);
get_as_area(callid, &call, sysinfo_value("klog.faddr"), sysinfo_value("klog.pages"), &klogaddr);
break;
default:
ipc_answer_0(callid, ENOENT);
162,14 → 241,6
continue;
}
break;
case NS_PING:
retval = EOK;
break;
case NS_TASK_WAIT:
id = (task_id_t)
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
wait_for_task(id, &call, callid);
continue;
default:
retval = ENOENT;
break;
183,6 → 254,213
return 0;
}
 
/** Register service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
{
unsigned long keys[3] = {
service,
call->in_phone_hash,
0
};
if (hash_table_find(&ns_hash_table, keys))
return EEXISTS;
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs)
return ENOMEM;
link_initialize(&hs->link);
hs->service = service;
hs->phone = phone;
hs->in_phone_hash = call->in_phone_hash;
hash_table_insert(&ns_hash_table, keys, &hs->link);
return 0;
}
 
/** Connect client to service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[3] = {
service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link) {
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
/* Blocking connection, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->service = service;
pr->callid = callid;
pr->arg2 = IPC_GET_ARG2(*call);
pr->arg3 = IPC_GET_ARG3(*call);
list_append(&pr->link, &pending_req);
return;
}
retval = ENOENT;
goto out;
}
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/** Register clonable service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
*/
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid)
{
if (list_empty(&cs_req)) {
/* There was no pending connection request. */
printf(NAME ": Unexpected clonable server.\n");
ipc_answer_0(callid, EBUSY);
return;
}
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
list_remove(&csr->link);
/* Currently we can only handle a single type of clonable service. */
assert(csr->service == SERVICE_LOAD);
ipc_answer_0(callid, EOK);
int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
 
free(csr);
ipc_hangup(phone);
}
 
/** Connect client to clonable service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid)
{
assert(service == SERVICE_LOAD);
cs_req_t *csr = malloc(sizeof(cs_req_t));
if (csr == NULL) {
ipc_answer_0(callid, ENOMEM);
return;
}
/* Spawn a loader. */
int rc = loader_spawn("loader");
if (rc < 0) {
free(csr);
ipc_answer_0(callid, rc);
return;
}
csr->service = service;
csr->call = *call;
csr->callid = callid;
/*
* We can forward the call only after the server we spawned connects
* to us. Meanwhile we might need to service more connection requests.
* Thus we store the call in a queue.
*/
list_append(&csr->link, &cs_req);
}
 
/** Compute hash index into NS hash table.
*
* @param key Pointer keys. However, only the first key (i.e. service number)
* is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
hash_index_t ns_hash(unsigned long *key)
{
assert(key);
return (*key % NS_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* This compare function always ignores the third key.
* It exists only to make it possible to remove records
* originating from connection with key[1] in_phone_hash
* value. Note that this is close to being classified
* as a nasty hack.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 3.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys <= 3);
assert(item);
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
if (keys == 2)
return key[1] == hs->in_phone_hash;
else
return key[0] == hs->service;
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
void ns_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/**
* @}
*/
/branches/network/uspace/srv/ns/Makefile
41,10 → 41,7
 
OUTPUT = ns
SOURCES = \
ns.c \
service.c \
clonable.c \
task.c
ns.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
66,7 → 63,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/srv/fhc/fhc.c
0,0 → 1,157
/*
* Copyright (c) 2009 Jakub Jermar
* 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 fhc
* @{
*/
 
/**
* @file fhc.c
* @brief FHC bus controller driver.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "fhc"
 
#define FHC_UART_INR 0x39
 
#define FHC_UART_IMAP 0x0
#define FHC_UART_ICLR 0x4
 
static void *fhc_uart_phys;
static volatile uint32_t *fhc_uart_virt;
static size_t fhc_uart_size;
 
/** Handle one connection to fhc.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
switch (inr) {
case FHC_UART_INR:
fhc_uart_virt[FHC_UART_ICLR] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
}
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the FHC driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone FHC driver.
*/
static bool fhc_init(void)
{
ipcarg_t phonead;
 
fhc_uart_size = sysinfo_value("fhc.uart.size");
fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical");
if (!fhc_uart_size) {
printf(NAME ": no FHC UART registers found\n");
return false;
}
 
fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt,
ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping FHC UART registers\n");
return false;
}
printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys,
fhc_uart_size);
 
async_set_client_connection(fhc_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS FHC bus controller driver\n");
if (!fhc_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
/branches/network/uspace/srv/fhc/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = fhc
SOURCES = \
fhc.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/network/uspace/srv/obio/obio.c
0,0 → 1,158
/*
* Copyright (c) 2009 Jakub Jermar
* 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 obio
* @{
*/
 
/**
* @file obio.c
* @brief OBIO driver.
*
* OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P,
* there is a piece of the root PCI bus controller address space, which
* contains interrupt mapping and clear registers for all on-board devices.
* Although UltraSPARC IIi and U2P are different in general, these registers can
* be found at the same addresses.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "obio"
 
#define OBIO_SIZE 0x1898
 
#define OBIO_IMR_BASE 0x200
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK))
 
#define OBIO_CIR_BASE 0x300
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK))
 
#define INO_MASK 0x1f
 
static void *base_phys;
static volatile uint64_t *base_virt;
 
/** Handle one connection to obio.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void obio_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
base_virt[OBIO_CIR(inr & INO_MASK)] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the OBIO driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone OBIO driver.
*/
static bool obio_init(void)
{
ipcarg_t phonead;
 
base_phys = (void *) sysinfo_value("obio.base.physical");
if (!base_phys) {
printf(NAME ": no OBIO registers found\n");
return false;
}
 
base_virt = as_get_mappable_page(OBIO_SIZE);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(base_phys, (void *) base_virt,
ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping OBIO registers\n");
return false;
}
printf(NAME ": OBIO registers with base at %p\n", base_phys);
 
async_set_client_connection(obio_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS OBIO driver\n");
if (!obio_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/uspace/srv/obio/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = obio
SOURCES = \
obio.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/network/uspace/srv/obio
Property changes:
Added: svn:mergeinfo
/branches/network/uspace/app/getvc/version.c
File deleted
/branches/network/uspace/app/getvc/getvc.c
File deleted
/branches/network/uspace/app/getvc/version.h
File deleted
/branches/network/uspace/app/getvc/Makefile
File deleted
/branches/network/uspace/app/getvc/getvc.h
File deleted
/branches/network/uspace/app/bdsh/input.c
32,10 → 32,10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/console.h>
#include <io/keycode.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <io/stream.h>
#include <console.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <errno.h>
#include <bool.h>
 
100,7 → 100,7
 
static void read_line(char *buffer, int n)
{
console_event_t ev;
kbd_event_t ev;
size_t offs, otmp;
wchar_t dec;
 
107,12 → 107,11
offs = 0;
while (true) {
fflush(stdout);
if (!console_get_event(fphone(stdin), &ev))
if (kbd_get_event(&ev) < 0)
return;
if (ev.type != KEY_PRESS)
if (ev.type == KE_RELEASE)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
if (ev.key == KC_BACKSPACE) {
132,8 → 131,9
continue;
}
if (ev.c >= ' ') {
//putchar(ev.c);
if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK)
putchar(ev.c);
console_putchar(ev.c);
}
}
putchar('\n');
147,11 → 147,9
{
char line[INPUT_MAX];
 
fflush(stdout);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
console_set_style(STYLE_EMPHASIS);
printf("%s", usr->prompt);
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
console_set_style(STYLE_NORMAL);
 
read_line(line, INPUT_MAX);
/* Make sure we don't have rubbish or a C/R happy user */
/branches/network/uspace/app/bdsh/cmds/modules/mv/mv.c
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mv/mv_def.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mv/entry.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mv/mv.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/bdd/entry.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/bdd/bdd.c
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/bdd/bdd_def.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/bdd/bdd.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mount/mount.c
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mount/mount_def.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mount/entry.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mount/mount.h
File deleted
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
37,7 → 37,6
#include <sys/stat.h>
#include <getopt.h>
#include <stdarg.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c
34,8 → 34,6
#include <fcntl.h>
#include <dirent.h>
#include <getopt.h>
#include <mem.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
/branches/network/uspace/app/bdsh/cmds/modules/kcon/kcon.c
30,8 → 30,7
 
#include <stdio.h>
#include <stdlib.h>
#include <io/console.h>
#include <vfs/vfs.h>
#include <console.h>
#include "config.h"
#include "util.h"
#include "errors.h"
66,7 → 65,7
return CMD_FAILURE;
}
 
console_kcon_enable(fphone(stdout));
console_kcon_enable();
 
return CMD_SUCCESS;
}
/branches/network/uspace/app/bdsh/cmds/modules/modules.h
20,7 → 20,6
#include "help/entry.h"
#include "mkdir/entry.h"
#include "rm/entry.h"
#include "bdd/entry.h"
#include "cat/entry.h"
#include "touch/entry.h"
#include "ls/entry.h"
27,8 → 26,6
#include "pwd/entry.h"
#include "sleep/entry.h"
#include "cp/entry.h"
#include "mv/entry.h"
#include "mount/entry.h"
#include "kcon/entry.h"
 
/* Each .def function fills the module_t struct with the individual name, entry
39,7 → 36,6
#include "help/help_def.h"
#include "mkdir/mkdir_def.h"
#include "rm/rm_def.h"
#include "bdd/bdd_def.h"
#include "cat/cat_def.h"
#include "touch/touch_def.h"
#include "ls/ls_def.h"
46,10 → 42,7
#include "pwd/pwd_def.h"
#include "sleep/sleep_def.h"
#include "cp/cp_def.h"
#include "mv/mv_def.h"
#include "mount/mount_def.h"
#include "kcon/kcon_def.h"
 
{NULL, NULL, NULL, NULL}
};
 
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat.c
87,8 → 87,7
off_t total = 0;
char *buff = NULL;
 
fd = open(fname, O_RDONLY);
if (fd < 0) {
if (-1 == (fd = open(fname, O_RDONLY))) {
printf("Unable to open %s\n", fname);
return 1;
}
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd.c
30,7 → 30,6
 
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
 
#include "config.h"
#include "errors.h"
/branches/network/uspace/app/bdsh/cmds/modules/module_aliases.h
12,7 → 12,6
* the entry point being reached. */
 
char *mod_aliases[] = {
"ren", "mv",
NULL, NULL
};
 
/branches/network/uspace/app/bdsh/exec.c
123,8 → 123,7
if (tid == 0) {
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd);
return 1;
} else {
return 0;
}
task_wait(tid);
return 0;
}
/branches/network/uspace/app/bdsh/Makefile
33,13 → 33,12
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
LIBBLOCK_PREFIX = ../../lib/libblock
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include -I$(LIBBLOCK_PREFIX)
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE)
 
PROGRAM = bdsh
52,7 → 51,6
cmds/modules/help/ \
cmds/modules/mkdir/ \
cmds/modules/rm/ \
cmds/modules/bdd/ \
cmds/modules/cat/ \
cmds/modules/touch/ \
cmds/modules/ls/ \
59,8 → 57,6
cmds/modules/pwd/ \
cmds/modules/sleep/ \
cmds/modules/cp/ \
cmds/modules/mv/ \
cmds/modules/mount/ \
cmds/modules/kcon/ \
cmds/builtins/ \
cmds/builtins/exit/\
70,7 → 66,6
cmds/modules/help/help.c \
cmds/modules/mkdir/mkdir.c \
cmds/modules/rm/rm.c \
cmds/modules/bdd/bdd.c \
cmds/modules/cat/cat.c \
cmds/modules/touch/touch.c \
cmds/modules/ls/ls.c \
77,8 → 72,6
cmds/modules/pwd/pwd.c \
cmds/modules/sleep/sleep.c \
cmds/modules/cp/cp.c \
cmds/modules/mv/mv.c \
cmds/modules/mount/mount.c \
cmds/modules/kcon/kcon.c \
cmds/builtins/exit/exit.c \
cmds/builtins/cd/cd.c \
/branches/network/uspace/app/init/init.c
44,31 → 44,25
#include <task.h>
#include <malloc.h>
#include <macros.h>
#include <console.h>
#include <string.h>
#include <devmap.h>
#include "init.h"
#include "version.h"
 
static void info_print(void)
static bool mount_fs(const char *fstype)
{
printf(NAME ": HelenOS init\n");
}
 
static bool mount_root(const char *fstype)
{
int rc = -1;
char *opts = "";
const char *root_dev = "initrd";
if (str_cmp(fstype, "tmpfs") == 0)
opts = "restore";
 
while (rc < 0) {
rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING);
rc = mount(fstype, "/", "initrd", opts, IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted, %s at %s\n",
fstype, root_dev);
printf(NAME ": Root filesystem mounted\n");
break;
case EBUSY:
printf(NAME ": Root filesystem already mounted\n");
85,32 → 79,6
return true;
}
 
static bool mount_devfs(void)
{
int rc = -1;
while (rc < 0) {
rc = mount("devfs", "/dev", "null", "", IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Device filesystem mounted\n");
break;
case EBUSY:
printf(NAME ": Device filesystem already mounted\n");
break;
case ELIMIT:
printf(NAME ": Unable to mount device filesystem\n");
return false;
case ENOENT:
printf(NAME ": Unknown filesystem type (devfs)\n");
return false;
}
}
return true;
}
 
static void spawn(char *fname)
{
char *argv[2];
124,62 → 92,16
printf(NAME ": Error spawning %s\n", fname);
}
 
static void getvc(char *dev, char *app)
{
char *argv[4];
char vc[MAX_DEVICE_NAME];
int rc;
snprintf(vc, MAX_DEVICE_NAME, "/dev/%s", dev);
printf(NAME ": Spawning getvc on %s\n", vc);
dev_handle_t handle;
rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
if (rc == EOK) {
argv[0] = "/app/getvc";
argv[1] = vc;
argv[2] = app;
argv[3] = NULL;
if (!task_spawn("/app/getvc", argv))
printf(NAME ": Error spawning getvc on %s\n", vc);
} else {
printf(NAME ": Error waiting on %s\n", vc);
}
}
 
void mount_data(void)
{
int rc;
 
printf("Trying to mount disk0 on /data... ");
fflush(stdout);
 
rc = mount("fat", "/data", "disk0", "wtcache", 0);
if (rc == EOK)
printf("OK\n");
else
printf("Failed\n");
}
 
int main(int argc, char *argv[])
{
info_print();
if (!mount_root(STRING(RDFMT))) {
if (!mount_fs(STRING(RDFMT))) {
printf(NAME ": Exiting\n");
return -1;
}
spawn("/srv/devfs");
if (!mount_devfs()) {
printf(NAME ": Exiting\n");
return -2;
}
// FIXME: spawn("/srv/pci");
spawn("/srv/fb");
spawn("/srv/kbd");
// spawn("/srv/netstart");
186,20 → 108,13
spawn("/srv/console");
spawn("/srv/fhc");
spawn("/srv/obio");
spawn("/srv/ata_bd");
spawn("/srv/gxe_bd");
 
usleep(250000);
mount_data();
 
getvc("vc0", "/app/bdsh");
getvc("vc1", "/app/bdsh");
getvc("vc2", "/app/bdsh");
getvc("vc3", "/app/bdsh");
getvc("vc4", "/app/bdsh");
getvc("vc5", "/app/bdsh");
getvc("vc6", "/app/klog");
console_wait();
version_print();
spawn("/app/klog");
spawn("/app/bdsh");
return 0;
}
 
/branches/network/uspace/app/init/version.c
0,0 → 1,69
/*
* Copyright (c) 2006 Jakub Jermar
* 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 init
* @{
*/
/**
* @file
*/
 
#include <unistd.h>
#include <stdio.h>
#include <macros.h>
#include "init.h"
#include "version.h"
 
char *release = STRING(RELEASE);
 
#ifdef REVISION
char *revision = ", revision " STRING(REVISION);
#else
char *revision = "";
#endif
 
#ifdef TIMESTAMP
char *timestamp = "\nBuilt on " STRING(TIMESTAMP);
#else
char *timestamp = "";
#endif
 
void info_print(void)
{
printf(NAME ": HelenOS init\n");
}
 
/** Print version information. */
void version_print(void)
{
printf("HelenOS init\nRelease %s%s%s\n", release, revision, timestamp);
printf("Copyright (c) 2001-2009 HelenOS project\n");
}
 
/** @}
*/
/branches/network/uspace/app/init/Makefile
26,6 → 26,8
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
 
## Setup toolchain
#
 
34,7 → 36,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE)
 
## Sources
#
41,7 → 46,8
 
OUTPUT = init
SOURCES = \
init.c
init.c \
version.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
63,7 → 69,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/app/init/init.h
28,7 → 28,7
 
/** @addtogroup init
* @{
*/
*/
/**
* @file
*/
36,11 → 36,10
#ifndef __INIT_H__
#define __INIT_H__
 
#define NAME "init"
#define NAME "init"
 
#define MAX_DEVICE_NAME 32
 
#endif
 
/** @}
*/
 
/branches/network/uspace/app/init/version.h
0,0 → 1,46
/*
* Copyright (c) 2006 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 init
* @{
*/
/**
* @file
*/
 
#ifndef __VERSION_H__
#define __VERSION_H__
 
extern void info_print(void);
extern void version_print(void);
 
#endif
 
/** @}
*/
 
/branches/network/uspace/app/tester/devmap/devmap1.c
32,7 → 32,7
#include <ipc/services.h>
#include <async.h>
#include <errno.h>
#include <devmap.h>
#include <ipc/devmap.h>
#include "../tester.h"
 
#include <time.h>
84,14 → 84,22
 
handle = (int)arg;
 
device_phone = devmap_device_connect(handle, 0);
device_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, handle);
 
if (device_phone < 0) {
printf("Failed to connect to device (handle = %u).\n",
printf("Failed to connect to devmap as client (handle = %u).\n",
handle);
return -1;
}
 
/*
* device_phone = (int) IPC_GET_ARG5(answer);
*/
printf("Connected to device.\n");
ipc_call_sync_1_0(device_phone, 1024, 1025);
/*
* ipc_hangup(device_phone);
*/
ipc_hangup(device_phone);
 
return EOK;
113,6 → 121,126
return EOK;
}
 
/**
*
*/
static int driver_register(char *name)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf("Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(phone, (char *)name, str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return -1;
}
 
async_set_client_connection(driver_client_connection);
 
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
/*
if (NULL == async_new_connection(callback_phonehash, 0, NULL,
driver_client_connection)) {
printf("Failed to create new fibril.\n");
async_wait_for(req, NULL);
return -1;
}
*/
async_wait_for(req, &retval);
printf("Driver '%s' registered.\n", name);
 
return phone;
}
 
static int device_get_handle(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0,
&answer);
 
retval = ipc_data_write_start(driver_phone, name, str_size(name) + 1);
 
if (retval != EOK) {
printf("Failed to send device name '%s'.\n", name);
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (NULL != handle) {
*handle = -1;
}
 
if (EOK == retval) {
if (NULL != handle) {
*handle = (int) IPC_GET_ARG1(answer);
}
printf("Device '%s' has handle %u.\n", name,
(int) IPC_GET_ARG1(answer));
} else {
printf("Failed to get handle for device '%s'.\n", name);
}
 
return retval;
}
 
/** Register new device.
* @param driver_phone
* @param name Device name.
* @param handle Output variable. Handle to the created instance of device.
*/
static int device_register(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(driver_phone, (char *)name,
str_size(name) + 1);
 
if (retval != EOK) {
printf("Failed to send device name '%s'.\n", name);
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (NULL != handle) {
*handle = -1;
}
 
if (EOK == retval) {
if (NULL != handle) {
*handle = (int) IPC_GET_ARG1(answer);
}
printf("Device registered with handle %u.\n",
(int) IPC_GET_ARG1(answer));
}
 
return retval;
}
 
/** Test DevMap from the driver's point of view.
*
*
119,71 → 247,64
*/
char * test_devmap1(bool quiet)
{
const char *retval = NULL;
int driver_phone;
int dev1_handle;
int dev2_handle;
int dev3_handle;
int handle;
 
/* Register new driver */
int rc = devmap_driver_register("TestDriver", driver_client_connection);
if (rc < 0) {
retval = "Error: Cannot register driver.\n";
goto out;
driver_phone = driver_register("TestDriver");
 
if (driver_phone < 0) {
return "Error: Cannot register driver.\n";
}
/* Register new device dev1. */
dev_handle_t dev1_handle;
rc = devmap_device_register(TEST_DEVICE1, &dev1_handle);
if (rc != EOK) {
retval = "Error: cannot register device.\n";
goto out;
 
/* Register new device dev1*/
if (EOK != device_register(driver_phone, TEST_DEVICE1, &dev1_handle)) {
ipc_hangup(driver_phone);
return "Error: cannot register device.\n";
}
/*
* Get handle for dev2 (Should fail unless device is already registered
* by someone else).
 
/* Get handle for dev2 (Should fail unless device is already
* registered by someone else)
*/
dev_handle_t handle;
rc = devmap_device_get_handle(TEST_DEVICE2, &handle, 0);
if (rc == EOK) {
retval = "Error: got handle for dev2 before it was registered.\n";
goto out;
if (EOK == device_get_handle(driver_phone, TEST_DEVICE2, &handle)) {
ipc_hangup(driver_phone);
return "Error: got handle for dev2 before it was registered.\n";
}
/* Register new device dev2. */
dev_handle_t dev2_handle;
rc = devmap_device_register(TEST_DEVICE2, &dev2_handle);
if (rc != EOK) {
retval = "Error: cannot register device dev2.\n";
goto out;
 
/* Register new device dev2*/
if (EOK != device_register(driver_phone, TEST_DEVICE2, &dev2_handle)) {
ipc_hangup(driver_phone);
return "Error: cannot register device dev2.\n";
}
/* Register device dev1 again. */
dev_handle_t dev3_handle;
rc = devmap_device_register(TEST_DEVICE1, &dev3_handle);
if (rc == EOK) {
retval = "Error: dev1 registered twice.\n";
goto out;
 
/* Register again device dev1 */
if (EOK == device_register(driver_phone, TEST_DEVICE1, &dev3_handle)) {
return "Error: dev1 registered twice.\n";
}
/* Get handle for dev1. */
rc = devmap_device_get_handle(TEST_DEVICE1, &handle, 0);
if (rc != EOK) {
retval = "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
goto out;
 
/* Get handle for dev1*/
if (EOK != device_get_handle(driver_phone, TEST_DEVICE1, &handle)) {
ipc_hangup(driver_phone);
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
}
 
if (handle != dev1_handle) {
retval = "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
goto out;
ipc_hangup(driver_phone);
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
}
if (device_client(dev1_handle) != EOK) {
retval = "Error: failed client test for 'DEVMAP_DEVICE1'.\n";
goto out;
 
if (EOK != device_client(dev1_handle)) {
ipc_hangup(driver_phone);
return "Error: failed client test for 'DEVMAP_DEVICE1'.\n";
}
out:
devmap_hangup_phone(DEVMAP_DRIVER);
devmap_hangup_phone(DEVMAP_CLIENT);
 
/* TODO: */
 
ipc_hangup(driver_phone);
 
return NULL;
}
 
/branches/network/uspace/app/tester/tester.c
56,7 → 56,6
#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"
130,7 → 129,6
list_tests();
printf("> ");
fflush(stdout);
c = getchar();
printf("%c\n", c);
/branches/network/uspace/app/tester/tester.h
69,7 → 69,6
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);
/branches/network/uspace/app/tester/Makefile
54,7 → 54,6
ipc/send_sync.c \
ipc/answer.c \
ipc/hangup.c \
ipc/ping_pong.c \
loop/loop1.c \
devmap/devmap1.c \
console/console1.c \
82,7 → 81,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/app/tester/console/console1.c
28,13 → 28,12
 
#include <stdio.h>
#include <stdlib.h>
#include <io/console.h>
#include <io/color.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <io/stream.h>
#include <async.h>
#include "../tester.h"
 
#include <console.h>
 
const char *color_name[] = {
[COLOR_BLACK] = "black",
[COLOR_BLUE] = "blue",
51,26 → 50,21
int i, j;
 
printf("Style test: ");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
console_set_style(STYLE_NORMAL);
printf("normal ");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
console_set_style(STYLE_EMPHASIS);
printf("emphasized");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
console_set_style(STYLE_NORMAL);
printf(".\n");
 
printf("Foreground color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
fflush(stdout);
console_set_color(fphone(stdout), i, COLOR_WHITE,
console_set_color(i, COLOR_WHITE,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
 
77,13 → 71,11
printf("Background color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
fflush(stdout);
console_set_color(fphone(stdout), COLOR_WHITE, i,
console_set_color(COLOR_WHITE, i,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
 
90,30 → 82,24
printf("Now let's test RGB colors:\n");
 
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 16);
console_set_rgb_color(0xffffff, i << 16);
putchar('X');
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8);
console_set_rgb_color(0xffffff, i << 8);
putchar('X');
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i);
console_set_rgb_color(0xffffff, i);
putchar('X');
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
printf("[press a key]\n");
/branches/network/uspace/app/tester/stdio/stdio2.c
35,6 → 35,7
{
FILE *f;
char *file_name = "/test";
size_t n;
int c;
 
printf("Open file '%s' for writing\n", file_name);
/branches/network/uspace/app/tester/ipc/ping_pong.c
File deleted
/branches/network/uspace/app/tester/ipc/ping_pong.def
File deleted
/branches/network/uspace/app/tetris/scores.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
48,18 → 48,24
*
* Major whacks since then.
*/
 
#include <errno.h>
/* #include <err.h> */
/* #include <fcntl.h> */
/* #include <pwd.h> */
#include <stdio.h>
/* #include <stdlib.h> */
#include <string.h>
#include <io/console.h>
#include <io/keycode.h>
#include <vfs/vfs.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <stdlib.h>
#include <fcntl.h>
#include <err.h>
#include <time.h>
/* #include <time.h> */
/* #include <term.h> */
/* #include <unistd.h> */
/* #include <sys/param.h> */
/* #include <sys/stat.h> */
/* #include <sys/types.h> */
 
#include "pathnames.h"
#include "screen.h"
#include "tetris.h"
#include "scores.h"
72,22 → 78,20
* As long as the scores are kept sorted, this is simply the first one at
* that level.
*/
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
/* static time_t now; */
/* static int nscores; */
/* static int gotscores; */
/* static struct highscore scores[NUMSPOTS]; */
static struct highscore scores[NUMSPOTS];
 
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
/* static int checkscores(struct highscore *, int); */
/* static int cmpscores(const void *, const void *); */
/* static void getscores(FILE **); */
/* static void printem(int, int, struct highscore *, int, const char *); */
/* static char *thisuser(void); */
 
void showscores(int firstgame)
{
97,55 → 101,59
moveto(10, 0);
printf("\tRank \tLevel \tName\t points\n");
printf("\t========================================================\n");
for (i = 0; i < NUMSPOTS - 1; i++)
printf("\t%6d %6d %-16s %20d\n",
i + 1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
for (i = 0; i < NUMSPOTS - 1; i++) {
printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
}
if (!firstgame) {
printf("\t========================================================\n");
printf("\t Last %6d %-16s %20d\n",
scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
printf("\t Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
}
printf("\n\n\n\n\tPress any key to return to main menu.");
getchar();
}
 
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
 
void insertscore(int score, int level)
{
int i;
int j;
int i,j;
size_t off;
console_event_t ev;
kbd_event_t ev;
clear_screen();
moveto(10, 10);
moveto(10 , 10);
puts("Insert your name: ");
str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
"Player");
i = 6;
off = 6;
i = 6; off = 6;
 
moveto(10 , 28);
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME-i,
"........................................");
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
 
while (1) {
fflush(stdout);
if (!console_get_event(fphone(stdin), &ev))
if (kbd_get_event(&ev) != EOK)
exit(1);
if (ev.type == KEY_RELEASE)
 
if (ev.type == KE_RELEASE)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
 
if (ev.key == KC_BACKSPACE) {
if (i > 0) {
wchar_t uc;
 
--i;
while (off > 0) {
--off;
155,7 → 163,7
if (uc != U_SPECIAL)
break;
}
 
scores[NUMSPOTS - 1].hs_name[off] = '\0';
}
} else if (ev.c != '\0') {
168,66 → 176,398
}
}
moveto(10, 28);
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i,
"........................................");
moveto(10 , 28);
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
}
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_level = level;
i = NUMSPOTS - 1;
i = NUMSPOTS-1;
while ((i > 0) && (scores[i - 1].hs_score < score))
i--;
for (j = NUMSPOTS - 2; j > i; j--)
copyhiscore(j, j-1);
copyhiscore(i, NUMSPOTS - 1);
 
for (j = NUMSPOTS - 2; j > i; j--) {
copyhiscore(j,j-1);
}
copyhiscore(i, NUMSPOTS - 1);
}
 
void initscores(void)
{
int i;
for (i = 0; i < NUMSPOTS; i++) {
for(i = 0; i < NUMSPOTS; i++) {
str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team");
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL ? MAXLEVEL : i + 1);
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1);
}
}
 
int loadscores(void)
{
FILE *f;
size_t cnt;
int rc;
/*
* Read the score file. Can be called from savescore (before showscores)
* or showscores (if savescore will not be called). If the given pointer
* is not NULL, sets *fpp to an open file pointer that corresponds to a
* read/write score file that is locked with LOCK_EX. Otherwise, the
* file is locked with LOCK_SH for the read and closed before return.
*
* Note, we assume closing the stdio file releases the lock.
*/
/* static void */
/* getscores(FILE **fpp) */
/* { */
/* int sd, mint, lck, mask, i; */
/* char *mstr, *human; */
/* FILE *sf; */
 
f = fopen("/data/tetris.sco", "rb");
if (f == NULL)
return ENOENT;
/* if (fpp != NULL) { */
/* mint = O_RDWR | O_CREAT; */
/* mstr = "r+"; */
/* human = "read/write"; */
/* lck = LOCK_EX; */
/* } else { */
/* mint = O_RDONLY; */
/* mstr = "r"; */
/* human = "reading"; */
/* lck = LOCK_SH; */
/* } */
/* setegid(egid); */
/* mask = umask(S_IWOTH); */
/* sd = open(_PATH_SCOREFILE, mint, 0666); */
/* (void)umask(mask); */
/* setegid(gid); */
/* if (sd < 0) { */
/* if (fpp == NULL) { */
/* nscores = 0; */
/* return; */
/* } */
/* err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */
/* } */
/* setegid(egid); */
/* if ((sf = fdopen(sd, mstr)) == NULL) */
/* err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */
/* setegid(gid); */
 
cnt = fread(scores, sizeof(struct highscore), NUMSPOTS, f);
rc = fclose(f);
/* /\* */
/* * Grab a lock. */
/* *\/ */
/* if (flock(sd, lck)) */
/* warn("warning: score file %s cannot be locked", */
/* _PATH_SCOREFILE); */
 
if (cnt != NUMSPOTS || rc != 0)
return EIO;
/* nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */
/* if (ferror(sf)) */
/* err(1, "error reading %s", _PATH_SCOREFILE); */
/* for (i = 0; i < nscores; i++) */
/* if (scores[i].hs_level < MINLEVEL || */
/* scores[i].hs_level > MAXLEVEL) */
/* errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */
 
return EOK;
}
/* if (fpp) */
/* *fpp = sf; */
/* else */
/* (void)fclose(sf); */
/* } */
 
void savescores(void)
void
savescore(int level)
{
FILE *f;
size_t cnt;
int rc;
return;
}
/* struct highscore *sp; */
/* int i; */
/* int change; */
/* FILE *sf; */
/* const char *me; */
 
f = fopen("/data/tetris.sco", "wb");
cnt = fwrite(scores, sizeof(struct highscore), NUMSPOTS, f);
rc = fclose(f);
/* getscores(&sf); */
/* gotscores = 1; */
/* (void)time(&now); */
 
if (cnt != NUMSPOTS || rc != 0)
printf("Error saving score table\n");
/* /\* */
/* * Allow at most one score per person per level -- see if we */
/* * can replace an existing score, or (easiest) do nothing. */
/* * Otherwise add new score at end (there is always room). */
/* *\/ */
/* change = 0; */
/* me = thisuser(); */
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */
/* if (sp->hs_level != level || str_cmp(sp->hs_name, me) != 0) */
/* continue; */
/* if (score > sp->hs_score) { */
/* (void)printf("%s bettered %s %d score of %d!\n", */
/* "\nYou", "your old level", level, */
/* sp->hs_score * sp->hs_level); */
/* sp->hs_score = score; /\* new score *\/ */
/* sp->hs_time = now; /\* and time *\/ */
/* change = 1; */
/* } else if (score == sp->hs_score) { */
/* (void)printf("%s tied %s %d high score.\n", */
/* "\nYou", "your old level", level); */
/* sp->hs_time = now; /\* renew it *\/ */
/* change = 1; /\* gotta rewrite, sigh *\/ */
/* } /\* else new score < old score: do nothing *\/ */
/* break; */
/* } */
/* if (i >= nscores) { */
/* strlcpy(sp->hs_name, me, sizeof sp->hs_name); */
/* sp->hs_level = level; */
/* sp->hs_score = score; */
/* sp->hs_time = now; */
/* nscores++; */
/* change = 1; */
/* } */
 
/* if (change) { */
/* /\* */
/* * Sort & clean the scores, then rewrite. */
/* *\/ */
/* nscores = checkscores(scores, nscores); */
/* rewind(sf); */
/* if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */
/* fflush(sf) == EOF) */
/* warnx("error writing %s: %s\n\t-- %s", */
/* _PATH_SCOREFILE, strerror(errno), */
/* "high scores may be damaged"); */
/* } */
/* (void)fclose(sf); /\* releases lock *\/ */
/* } */
 
/*
* Get login name, or if that fails, get something suitable.
* The result is always trimmed to fit in a score.
*/
/* static char * */
/* thisuser(void) */
/* { */
/* const char *p; */
/* struct passwd *pw; */
/* static char u[sizeof(scores[0].hs_name)]; */
 
/* if (u[0]) */
/* return (u); */
/* p = getlogin(); */
/* if (p == NULL || *p == '\0') { */
/* pw = getpwuid(getuid()); */
/* if (pw != NULL) */
/* p = pw->pw_name; */
/* else */
/* p = " ???"; */
/* } */
/* strlcpy(u, p, sizeof(u)); */
/* return (u); */
/* } */
 
/*
* Score comparison function for qsort.
*
* If two scores are equal, the person who had the score first is
* listed first in the highscore file.
*/
/* static int */
/* cmpscores(const void *x, const void *y) */
/* { */
/* const struct highscore *a, *b; */
/* long l; */
 
/* a = x; */
/* b = y; */
/* l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */
/* if (l < 0) */
/* return (-1); */
/* if (l > 0) */
/* return (1); */
/* if (a->hs_time < b->hs_time) */
/* return (-1); */
/* if (a->hs_time > b->hs_time) */
/* return (1); */
/* return (0); */
/* } */
 
/*
* If we've added a score to the file, we need to check the file and ensure
* that this player has only a few entries. The number of entries is
* controlled by MAXSCORES, and is to ensure that the highscore file is not
* monopolised by just a few people. People who no longer have accounts are
* only allowed the highest score. Scores older than EXPIRATION seconds are
* removed, unless they are someone's personal best.
* Caveat: the highest score on each level is always kept.
*/
/* static int */
/* checkscores(struct highscore *hs, int num) */
/* { */
/* struct highscore *sp; */
/* int i, j, k, numnames; */
/* int levelfound[NLEVELS]; */
/* struct peruser { */
/* char *name; */
/* int times; */
/* } count[NUMSPOTS]; */
/* struct peruser *pu; */
 
/* /\* */
/* * Sort so that highest totals come first. */
/* * */
/* * levelfound[i] becomes set when the first high score for that */
/* * level is encountered. By definition this is the highest score. */
/* *\/ */
/* qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* numnames = 0; */
/* for (i = 0, sp = hs; i < num;) { */
/* /\* */
/* * This is O(n^2), but do you think we care? */
/* *\/ */
/* for (j = 0, pu = count; j < numnames; j++, pu++) */
/* if (str_cmp(sp->hs_name, pu->name) == 0) */
/* break; */
/* if (j == numnames) { */
/* /\* */
/* * Add new user, set per-user count to 1. */
/* *\/ */
/* pu->name = sp->hs_name; */
/* pu->times = 1; */
/* numnames++; */
/* } else { */
/* /\* */
/* * Two ways to keep this score: */
/* * - Not too many (per user), still has acct, & */
/* * score not dated; or */
/* * - High score on this level. */
/* *\/ */
/* if ((pu->times < MAXSCORES && */
/* getpwnam(sp->hs_name) != NULL && */
/* sp->hs_time + EXPIRATION >= now) || */
/* levelfound[sp->hs_level] == 0) */
/* pu->times++; */
/* else { */
/* /\* */
/* * Delete this score, do not count it, */
/* * do not pass go, do not collect $200. */
/* *\/ */
/* num--; */
/* for (k = i; k < num; k++) */
/* hs[k] = hs[k + 1]; */
/* continue; */
/* } */
/* } */
/* levelfound[sp->hs_level] = 1; */
/* i++, sp++; */
/* } */
/* return (num > MAXHISCORES ? MAXHISCORES : num); */
/* } */
 
/*
* Show current scores. This must be called after savescore, if
* savescore is called at all, for two reasons:
* - Showscores munches the time field.
* - Even if that were not the case, a new score must be recorded
* before it can be shown anyway.
*/
/*
void
showscores(int level)
{
return;
}
*/
/* struct highscore *sp; */
/* int i, n, c; */
/* const char *me; */
/* int levelfound[NLEVELS]; */
 
/* if (!gotscores) */
/* getscores((FILE **)NULL); */
/* (void)printf("\n\t\t Tetris High Scores\n"); */
 
/* /\* */
/* * If level == 0, the person has not played a game but just asked for */
/* * the high scores; we do not need to check for printing in highlight */
/* * mode. If SOstr is null, we can't do highlighting anyway. */
/* *\/ */
/* me = level && SOstr ? thisuser() : NULL; */
 
/* /\* */
/* * Set times to 0 except for high score on each level. */
/* *\/ */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* for (i = 0, sp = scores; i < nscores; i++, sp++) { */
/* if (levelfound[sp->hs_level]) */
/* sp->hs_time = 0; */
/* else { */
/* sp->hs_time = 1; */
/* levelfound[sp->hs_level] = 1; */
/* } */
/* } */
 
/* /\* */
/* * Page each screenful of scores. */
/* *\/ */
/* for (i = 0, sp = scores; i < nscores; sp += n) { */
/* n = 20; */
/* if (i + n > nscores) */
/* n = nscores - i; */
/* printem(level, i + 1, sp, n, me); */
/* if ((i += n) < nscores) { */
/* (void)printf("\nHit RETURN to continue."); */
/* (void)fflush(stdout); */
/* while ((c = getchar()) != '\n') */
/* if (c == EOF) */
/* break; */
/* (void)printf("\n"); */
/* } */
/* } */
 
/* if (nscores == 0) */
/* printf("\t\t\t - none to date.\n"); */
/* } */
 
/* static void */
/* printem(int level, int offset, struct highscore *hs, int n, const char *me) */
/* { */
/* struct highscore *sp; */
/* int row, highlight, i; */
/* char buf[100]; */
/* #define TITLE "Rank Score Name (points/level)" */
/* #define TITL2 "==========================================================" */
 
/* printf("%s\n%s\n", TITLE, TITL2); */
 
/* highlight = 0; */
 
/* for (row = 0; row < n; row++) { */
/* sp = &hs[row]; */
/* (void)snprintf(buf, sizeof(buf), */
/* "%3d%c %6d %-31s (%6d on %d)\n", */
/* row + offset, sp->hs_time ? '*' : ' ', */
/* sp->hs_score * sp->hs_level, */
/* sp->hs_name, sp->hs_score, sp->hs_level); */
/* /\* Print leaders every three lines *\/ */
/* if ((row + 1) % 3 == 0) { */
/* for (i = 0; i < sizeof(buf); i++) */
/* if (buf[i] == ' ') */
/* buf[i] = '_'; */
/* } */
/* /\* */
/* * Highlight if appropriate. This works because */
/* * we only get one score per level. */
/* *\/ */
/* if (me != NULL && */
/* sp->hs_level == level && */
/* sp->hs_score == score && */
/* str_cmp(sp->hs_name, me) == 0) { */
/* putpad(SOstr); */
/* highlight = 1; */
/* } */
/* (void)printf("%s", buf); */
/* if (highlight) { */
/* putpad(SEstr); */
/* highlight = 0; */
/* } */
/* } */
/* } */
 
/** @}
*/
 
/branches/network/uspace/app/tetris/input.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
57,9 → 57,9
#include "tetris.h"
 
#include <async.h>
#include <vfs/vfs.h>
#include <io/console.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
 
/* return true iff the given timeval is positive */
#define TV_POS(tv) \
92,12 → 92,14
* Return 0 => no input, 1 => can read() from stdin
*
*/
int rwait(struct timeval *tvp)
int
rwait(struct timeval *tvp)
{
struct timeval starttv, endtv, *s;
static ipc_call_t charcall;
ipcarg_t rc;
int cons_phone;
 
/*
* Someday, select() will do this for us.
* Just in case that day is now, and no one has
109,15 → 111,15
s = &endtv;
} else
s = NULL;
 
if (!lastchar) {
again:
if (!getchar_inprog) {
getchar_inprog = async_send_0(fphone(stdin),
CONSOLE_GET_EVENT, &charcall);
cons_phone = console_open(true);
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETKEY, 0, 0, &charcall);
}
if (!s)
if (!s)
async_wait_for(getchar_inprog, &rc);
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
tvp->tv_sec = 0;
124,25 → 126,22
tvp->tv_usec = 0;
return (0);
}
getchar_inprog = 0;
if (rc)
if (rc) {
stop("end of file, help");
if (IPC_GET_ARG1(charcall) == KEY_RELEASE)
}
if (IPC_GET_ARG1(charcall) == KE_RELEASE)
goto again;
 
lastchar = IPC_GET_ARG4(charcall);
}
if (tvp) {
/* since there is input, we may not have timed out */
(void) gettimeofday(&endtv, NULL);
TV_SUB(&endtv, &starttv);
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
}
return 1;
return (1);
}
 
/*
149,10 → 148,11
* `sleep' for the current turn time (using select).
* Eat any input that might be available.
*/
void tsleep(void)
void
tsleep(void)
{
struct timeval tv;
 
tv.tv_sec = 0;
tv.tv_usec = fallrate;
while (TV_POS(&tv))
165,11 → 165,12
/*
* getchar with timeout.
*/
int tgetchar(void)
int
tgetchar(void)
{
static struct timeval timeleft;
char c;
 
/*
* Reset timeleft to fallrate whenever it is not positive.
* In any case, wait to see if there is any input. If so,
180,18 → 181,17
* Most of the hard work is done by rwait().
*/
if (!TV_POS(&timeleft)) {
faster(); /* go faster */
faster(); /* go faster */
timeleft.tv_sec = 0;
timeleft.tv_usec = fallrate;
}
if (!rwait(&timeleft))
return -1;
return (-1);
c = lastchar;
lastchar = '\0';
return ((int) (unsigned char) c);
return ((int)(unsigned char)c);
}
 
/** @}
*/
 
/branches/network/uspace/app/tetris/screen.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,24 → 50,21
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vfs/vfs.h>
#include <console.h>
 
#include <async.h>
#include "screen.h"
#include "tetris.h"
#include <io/console.h>
#include <ipc/console.h>
 
#define STOP (B_COLS - 3)
 
static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */
static int curscore;
static int isset; /* true => terminal is in game mode */
static int isset; /* true => terminal is in game mode */
 
static const struct shape *lastshape;
 
 
/*
* putstr() is for unpadded strings (either as in termcap(5) or
* simply literal strings);
* simply literal strings);
*/
static inline void putstr(char *s)
{
75,21 → 72,19
putchar(*(s++));
}
 
static void start_standout(uint32_t color)
static void start_standout(void)
{
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xf0f0f0, color);
console_set_rgb_color(0xf0f0f0, 0);
}
 
static void resume_normal(void)
{
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0, 0xf0f0f0);
console_set_rgb_color(0, 0xf0f0f0);
}
 
void clear_screen(void)
{
console_clear(fphone(stdout));
console_clear();
moveto(0, 0);
}
 
96,20 → 91,23
/*
* Clear the screen, forgetting the current contents in the process.
*/
void scr_clear(void)
void
scr_clear(void)
{
 
resume_normal();
console_clear(fphone(stdout));
console_clear();
curscore = -1;
memset(curscreen, 0, sizeof(curscreen));
memset((char *)curscreen, 0, sizeof(curscreen));
}
 
/*
* Set up screen
*/
void scr_init(void)
void
scr_init(void)
{
console_cursor_visibility(fphone(stdout), 0);
console_cursor_visibility(0);
resume_normal();
scr_clear();
}
116,8 → 114,7
 
void moveto(int r, int c)
{
fflush(stdout);
console_goto(fphone(stdout), c, r);
console_goto(r, c);
}
 
winsize_t winsize;
124,27 → 121,25
 
static int get_display_size(winsize_t *ws)
{
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row);
return console_get_size(&ws->ws_row, &ws->ws_col);
}
 
/*
* Set up screen mode.
*/
void scr_set(void)
void
scr_set(void)
{
winsize_t ws;
Rows = 0;
Cols = 0;
 
Rows = 0, Cols = 0;
if (get_display_size(&ws) == 0) {
Rows = ws.ws_row;
Cols = ws.ws_col;
}
if ((Rows < MINROWS) || (Cols < MINCOLS)) {
if (Rows < MINROWS || Cols < MINCOLS) {
char smallscr[55];
 
snprintf(smallscr, sizeof(smallscr),
"the screen is too small (must be at least %dx%d)",
MINROWS, MINCOLS);
151,7 → 146,7
stop(smallscr);
}
isset = 1;
 
scr_clear();
}
 
158,80 → 153,76
/*
* End screen mode.
*/
void scr_end(void)
void
scr_end(void)
{
console_cursor_visibility(fphone(stdout), 1);
}
 
void stop(char *why)
void
stop(char *why)
{
 
if (isset)
scr_end();
errx(1, "aborting: %s", why);
}
 
 
/*
* Update the screen.
*/
void scr_update(void)
void
scr_update(void)
{
cell *bp;
cell *sp;
cell so;
cell cur_so = 0;
int i;
int j;
int ccol;
/* Always leave cursor after last displayed point */
cell *bp, *sp;
cell so, cur_so = 0;
int i, ccol, j;
static const struct shape *lastshape;
 
/* always leave cursor after last displayed point */
curscreen[D_LAST * B_COLS - 1] = -1;
 
if (score != curscore) {
moveto(0, 0);
printf("Score: %d", score);
curscore = score;
}
/* Draw preview of next pattern */
if ((showpreview) && (nextshape != lastshape)) {
 
/* draw preview of next pattern */
if (showpreview && (nextshape != lastshape)) {
int i;
static int r = 5, c = 2;
static int r=5, c=2;
int tr, tc, t;
 
lastshape = nextshape;
/* Clean */
 
/* clean */
resume_normal();
moveto(r - 1, c - 1);
putstr(" ");
moveto(r, c - 1);
putstr(" ");
moveto(r + 1, c - 1);
putstr(" ");
moveto(r + 2, c - 1);
putstr(" ");
moveto(r - 3, c - 2);
moveto(r-1, c-1); putstr(" ");
moveto(r, c-1); putstr(" ");
moveto(r+1, c-1); putstr(" ");
moveto(r+2, c-1); putstr(" ");
 
moveto(r-3, c-2);
putstr("Next shape:");
/* Draw */
start_standout(nextshape->color);
 
/* draw */
start_standout();
moveto(r, 2 * c);
putstr(" ");
for (i = 0; i < 3; i++) {
t = c + r * B_COLS;
t += nextshape->off[i];
 
tr = t / B_COLS;
tc = t % B_COLS;
 
moveto(tr, 2*tc);
putstr(" ");
}
resume_normal();
}
 
bp = &board[D_FIRST * B_COLS];
sp = &curscreen[D_FIRST * B_COLS];
for (j = D_FIRST; j < D_LAST; j++) {
239,7 → 230,6
for (i = 0; i < B_COLS; bp++, sp++, i++) {
if (*sp == (so = *bp))
continue;
*sp = so;
if (i != ccol) {
if (cur_so) {
248,16 → 238,15
}
moveto(RTOD(j), CTOD(i));
}
if (so != cur_so) {
if (so)
start_standout(so);
start_standout();
else
resume_normal();
cur_so = so;
}
putstr(" ");
 
ccol = i + 1;
/*
* Look ahead a bit, to avoid extra motion if
267,35 → 256,33
* `unnecessarily'. Skip it all, though, if
* the next cell is a different color.
*/
if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
#define STOP (B_COLS - 3)
if (i > STOP || sp[1] != bp[1] || so != bp[1])
continue;
if (sp[2] != bp[2])
sp[1] = -1;
else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
sp[2] = -1;
sp[1] = -1;
}
}
}
if (cur_so)
resume_normal();
fflush(stdout);
fflush(stdout);
}
 
/*
* Write a message (set != 0), or clear the same message (set == 0).
* Write a message (set!=0), or clear the same message (set==0).
* (We need its length in case we have to overwrite with blanks.)
*/
void scr_msg(char *s, int set)
void
scr_msg(char *s, int set)
{
int l = str_size(s);
moveto(Rows - 2, ((Cols - l) >> 1) - 1);
if (set)
putstr(s);
else
305,3 → 292,4
 
/** @}
*/
 
/branches/network/uspace/app/tetris/tetris.c
36,25 → 36,30
*/
 
/** @addtogroup tetris Tetris
* @brief Tetris ported from OpenBSD
* @{
* @brief Tetris ported from OpenBSD
* @{
*/
/** @file
*/
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1992, 1993\n"
"\tThe Regents of the University of California. All rights reserved.\n";
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
 
/*
* Tetris (or however it is spelled).
*/
 
#include <sys/time.h>
#include <sys/types.h>
 
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
 
#include "input.h"
#include "scores.h"
61,76 → 66,66
#include "screen.h"
#include "tetris.h"
 
cell board[B_SIZE];
 
int Rows;
int Cols;
 
cell board[B_SIZE];
int Rows, Cols;
const struct shape *curshape;
const struct shape *nextshape;
long fallrate;
int score;
//gid_t gid, egid;
char key_msg[100];
int showpreview, classic;
 
long fallrate;
int score;
char key_msg[100];
int showpreview;
int classic;
static void elide(void);
static void setup_board(void);
const struct shape *randshape(void);
void onintr(int);
void usage(void);
 
static void elide(void);
static void setup_board(void);
static const struct shape *randshape(void);
 
static void usage(void);
 
static int firstgame = 1;
 
/*
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* right edges are set.
*/
static void setup_board(void)
static void
setup_board(void)
{
int i;
cell *p = board;
cell *p;
 
p = board;
for (i = B_SIZE; i; i--)
*p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
*p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
}
 
/*
* Elide any full active rows.
*/
static void elide(void)
static void
elide(void)
{
int rows = 0;
int i;
int j;
int base;
int i, j, base;
cell *p;
 
for (i = A_FIRST; i < A_LAST; i++) {
base = i * B_COLS + 1;
p = &board[base];
for (j = B_COLS - 2; *p++ != 0;) {
if (--j <= 0) {
/* This row is to be elided */
/* this row is to be elided */
rows++;
memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
memset(&board[base], 0, B_COLS - 2);
scr_update();
tsleep();
while (--base != 0)
board[base + B_COLS] = board[base];
scr_update();
tsleep();
break;
}
}
}
switch (rows) {
case 1:
score += 10;
149,15 → 144,16
}
}
 
const struct shape *randshape(void)
const struct shape *
randshape(void)
{
const struct shape *tmp = &shapes[random() % 7];
int i;
int j = random() % 4;
const struct shape *tmp;
int i, j;
 
tmp = &shapes[random() % 7];
j = random() % 4;
for (i = 0; i < j; i++)
tmp = &shapes[classic ? tmp->rotc : tmp->rot];
tmp = &shapes[classic? tmp->rotc : tmp->rot];
return (tmp);
}
 
164,7 → 160,7
static void srandomdev(void)
{
struct timeval tv;
 
gettimeofday(&tv, NULL);
srandom(tv.tv_sec + tv.tv_usec / 100000);
}
171,43 → 167,61
 
static void tetris_menu_draw(int level)
{
clear_screen();
moveto(5, 10);
puts("Tetris\n\n");
moveto(8, 10);
printf("Level = %d (press keys 1 - 9 to change)", level);
moveto(9, 10);
printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
moveto(12, 10);
printf("Press 'h' to show hiscore table.");
moveto(13, 10);
printf("Press 's' to start game.");
moveto(14, 10);
printf("Press 'q' to quit game.");
moveto(20, 10);
printf("In game controls:");
moveto(21, 0);
puts(key_msg);
clear_screen();
moveto(5,10);
puts("Tetris\n\n");
moveto(8,10);
printf("Level = %d (press keys 1 - 9 to change)",level);
moveto(9,10);
printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off"));
moveto(12,10);
printf("Press 'h' to show hiscore table.");
moveto(13,10);
printf("Press 's' to start game.");
moveto(14,10);
printf("Press 'q' to quit game.");
moveto(20,10);
printf("In game controls:");
moveto(21,0);
puts(key_msg);
}
 
static int tetris_menu(int *level)
static int tetris_menu(int *level)
{
static int firstgame = 1;
int i;
/* if (showpreview == 0)
(void)printf("Your score: %d point%s x level %d = %d\n",
score, score == 1 ? "" : "s", level, score * level);
else {
(void)printf("Your score: %d point%s x level %d x preview penalty %0.3f = %d\n",
score, score == 1 ? "" : "s", level, (double)PRE_PENALTY,
(int)(score * level * PRE_PENALTY));
score = score * PRE_PENALTY;
}
savescore(level);
 
showscores(level);
printf("\nHit 's' to new game, 'q' to quit.\n");
*/
tetris_menu_draw(*level);
while (1) {
int i = getchar();
i = getchar();
switch(i) {
case 'p':
showpreview = !showpreview;
moveto(9, 21);
moveto(9,21);
if (showpreview)
printf("on ");
else
printf("off");
break;
case 'h':
loadscores();
showscores(firstgame);
tetris_menu_draw(*level);
break;
221,103 → 235,112
case '3':
case '4':
case '5':
case '6':
case '6':
case '7':
case '8':
case '9':
*level = i - '0';
moveto(8, 18);
moveto(8,18);
printf("%d", *level);
break;
}
}
}
 
int main(int argc, char *argv[])
int
main(int argc, char *argv[])
{
int pos;
int c;
int pos, c;
char *keys;
int level = 2;
char key_write[6][10];
int i;
int j;
int ch;
int i, j;
 
keys = "jkl pq";
 
// gid = getgid();
// egid = getegid();
// setegid(gid);
 
classic = 0;
showpreview = 1;
 
/* while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */
/* switch(ch) { */
/* case 'c': */
/* /\* */
/* * this means: */
/* * - rotate the other way; */
/* * - no reverse video. */
/* *\/ */
/* classic = 1; */
/* break; */
/* case 'k': */
/* if (str_size(keys = optarg) != 6) */
/* usage(); */
/* break; */
/* case 'l': */
/* level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */
/* &errstr); */
/* if (errstr) */
/* errx(1, "level must be from %d to %d", */
/* MINLEVEL, MAXLEVEL); */
/* break; */
/* case 'p': */
/* showpreview = 1; */
/* break; */
/* case 's': */
/* showscores(0); */
/* exit(0); */
/* default: */
/* usage(); */
/* } */
 
/* argc -= optind; */
/* argv += optind; */
 
/* if (argc) */
/* usage(); */
 
while ((ch = getopt(argc, argv, "ck:ps")) != -1)
switch(ch) {
case 'c':
/*
* this means:
* - rotate the other way
* - no reverse video
*/
classic = 1;
break;
case 'k':
if (str_size(keys = optarg) != 6)
usage();
break;
case 'p':
showpreview = 1;
break;
case 's':
showscores(0);
exit(0);
default:
usage();
}
argc -= optind;
argv += optind;
if (argc)
usage();
 
for (i = 0; i <= 5; i++) {
for (j = i + 1; j <= 5; j++) {
for (j = i+1; j <= 5; j++) {
if (keys[i] == keys[j])
errx(1, "duplicate command keys specified.");
}
if (keys[i] == ' ')
str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
str_cpy(key_write[i], sizeof key_write[i], "<space>");
else {
key_write[i][0] = keys[i];
key_write[i][1] = '\0';
}
}
snprintf(key_msg, sizeof(key_msg),
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
 
snprintf(key_msg, sizeof key_msg,
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
 
scr_init();
if (loadscores() != EOK)
initscores();
 
initscores();
while (tetris_menu(&level)) {
fallrate = 1000000 / level;
scr_clear();
setup_board();
srandomdev();
scr_set();
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
nextshape = randshape();
curshape = randshape();
scr_msg(key_msg, 1);
while (1) {
for (;;) {
place(curshape, pos, 1);
scr_update();
place(curshape, pos, 0);
330,7 → 353,7
pos += B_COLS;
continue;
}
/*
* Put up the current shape `permanently',
* bump score, and elide any full rows.
338,7 → 361,7
place(curshape, pos, 1);
score++;
elide();
/*
* Choose a new shape. If it does not fit,
* the game is over.
345,14 → 368,12
*/
curshape = nextshape;
nextshape = randshape();
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
if (!fits_in(curshape, pos))
break;
continue;
}
/*
* Handle command keys.
*/
360,11 → 381,10
/* quit */
break;
}
if (c == keys[4]) {
static char msg[] =
"paused - press RETURN to continue";
place(curshape, pos, 1);
do {
scr_update();
371,14 → 391,12
scr_msg(key_msg, 0);
scr_msg(msg, 1);
(void) fflush(stdout);
} while (rwait((struct timeval *) NULL) == -1);
} while (rwait((struct timeval *)NULL) == -1);
scr_msg(msg, 0);
scr_msg(key_msg, 1);
place(curshape, pos, 0);
continue;
}
if (c == keys[0]) {
/* move left */
if (fits_in(curshape, pos - 1))
385,17 → 403,15
pos--;
continue;
}
if (c == keys[1]) {
/* turn */
const struct shape *new =
&shapes[classic ? curshape->rotc : curshape->rot];
const struct shape *new = &shapes[
classic? curshape->rotc : curshape->rot];
if (fits_in(new, pos))
curshape = new;
continue;
}
if (c == keys[2]) {
/* move right */
if (fits_in(curshape, pos + 1))
402,7 → 418,6
pos++;
continue;
}
if (c == keys[3]) {
/* move to bottom */
while (fits_in(curshape, pos + B_COLS)) {
411,7 → 426,6
}
continue;
}
if (c == '\f') {
scr_clear();
scr_msg(key_msg, 1);
419,24 → 433,37
}
scr_clear();
loadscores();
insertscore(score, level);
savescores();
score = 0;
score=0;
}
scr_clear();
printf("\nGame over.\n");
printf("\n\n\n\t\tGame over.\n");
/*
while ((i = getchar()) != '\n')
if (i == EOF)
break
*/
scr_end();
 
return 0;
}
 
void usage(void)
/* void */
/* onintr(int signo) */
/* { */
/* scr_clear(); /\* XXX signal race *\/ */
/* scr_end(); /\* XXX signal race *\/ */
/* _exit(0); */
/* } */
 
void
usage(void)
{
fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
(void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n");
exit(1);
}
 
/** @}
*/
 
/branches/network/uspace/app/tetris/scores.h
34,9 → 34,8
*
* @(#)scores.h 8.1 (Berkeley) 5/31/93
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
45,27 → 44,26
/*
* Tetris scores.
*/
 
#include <sys/time.h>
#include <string.h>
 
#define MAXLOGNAME 16
#define MAXHISCORES 10
#define MAXSCORES 9 /* maximum high score entries per person */
#define EXPIRATION (5L * 365 * 24 * 60 * 60)
 
#define MAXLOGNAME 16
struct highscore {
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
time_t hs_time; /* time at game end */
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
// time_t hs_time; /* time at game end */
};
 
extern void showscores(int);
extern void initscores(void);
extern void insertscore(int score, int level);
extern int loadscores(void);
extern void savescores(void);
#define MAXHISCORES 10
//#define MAXSCORES 9 /* maximum high score entries per person */
//#define EXPIRATION (5L * 365 * 24 * 60 * 60)
 
void savescore(int);
void showscores(int);
void insertscore(int score, int level);
void initscores(void);
 
/** @}
*/
 
/branches/network/uspace/app/tetris/screen.h
36,37 → 36,36
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
/*
* putpad() is for padded strings with count = 1.
* putpad() is for padded strings with count=1.
*/
#define putpad(s) tputs(s, 1, put)
#define putpad(s) tputs(s, 1, put)
 
#include <sys/types.h>
#include <async.h>
 
typedef struct {
ipcarg_t ws_row;
ipcarg_t ws_col;
int ws_row;
int ws_col;
} winsize_t;
 
extern winsize_t winsize;
 
extern void moveto(int r, int c);
extern void clear_screen(void);
void moveto(int r, int c);
void clear_screen(void);
 
/* just calls putchar; for tputs */
extern int put(int);
extern void scr_clear(void);
extern void scr_end(void);
extern void scr_init(void);
extern void scr_msg(char *, int);
extern void scr_set(void);
extern void scr_update(void);
int put(int); /* just calls putchar; for tputs */
void scr_clear(void);
void scr_end(void);
void scr_init(void);
void scr_msg(char *, int);
void scr_set(void);
void scr_update(void);
 
/** @}
*/
 
/branches/network/uspace/app/tetris/Makefile
27,7 → 27,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/app/tetris/tetris.h
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
55,60 → 55,57
* worrying about addressing problems.
*/
 
/* The board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
/* the board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
 
typedef uint32_t cell;
typedef unsigned char cell;
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
 
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
/* the displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
 
/* The displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
/* the active area (rows) */
#define A_FIRST 1
#define A_LAST 21
 
/* The active area (rows) */
#define A_FIRST 1
#define A_LAST 21
 
/*
* Minimum display size.
*/
#define MINROWS 23
#define MINCOLS 40
#define MINROWS 23
#define MINCOLS 40
 
/* Current screen size */
extern int Rows;
extern int Cols;
extern int Rows, Cols; /* current screen size */
 
/*
* Translations from board coordinates to display coordinates.
* As with board coordinates, display coordiates are zero origin.
*/
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
 
/*
* A `shape' is the fundamental thing that makes up the game. There
* are 7 basic shapes, each consisting of four `blots':
*
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
*
* 0 1 2 3 4 5 6
* 0 1 2 3 4 5 6
*
* Except for 3 and 6, the center of each shape is one of the blots.
* This blot is designated (0, 0). The other three blots can then be
* This blot is designated (0,0). The other three blots can then be
* described as offsets from the center. Shape 3 is the same under
* rotation, so its center is effectively irrelevant; it has been chosen
* so that it `sticks out' upward and leftward. Except for shape 6,
* all the blots are contained in a box going from (-1, -1) to (+1, +1);
* all the blots are contained in a box going from (-1,-1) to (+1,+1);
* shape 6's center `wobbles' as it rotates, so that while it `sticks out'
* rightward, its rotation---a vertical line---`sticks out' downward.
* The containment box has to include the offset (2, 0), making the overall
* containment box range from offset (-1, -1) to (+2, +1). (This is why
* The containment box has to include the offset (2,0), making the overall
* containment box range from offset (-1,-1) to (+2,+1). (This is why
* there is only one row above, but two rows below, the display area.)
*
* The game works by choosing one of these shapes at random and putting
119,7 → 116,7
* At this time, any completely filled rows are elided, and blots above
* these rows move down to make more room. A new random shape is again
* introduced at the top of the board, and the whole process repeats.
* The game ends when the new shape will not fit at (1, 5).
* The game ends when the new shape will not fit at (1,5).
*
* While the shapes are falling, the user can rotate them counterclockwise
* 90 degrees (in addition to moving them left or right), provided that the
131,10 → 128,9
* rotated forms.
*/
struct shape {
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
uint32_t color;
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
};
 
extern const struct shape shapes[];
152,16 → 148,15
* The value eventually reaches a limit, and things stop going faster,
* but by then the game is utterly impossible.
*/
extern long fallrate; /* less than 1 million; smaller => faster */
extern long fallrate; /* less than 1 million; smaller => faster */
#define faster() (fallrate -= fallrate / 3000)
 
#define faster() (fallrate -= fallrate / 3000)
 
/*
* Game level must be between 1 and 9. This controls the initial fall rate
* and affects scoring.
*/
#define MINLEVEL 1
#define MAXLEVEL 9
#define MINLEVEL 1
#define MAXLEVEL 9
 
/*
* Scoring is as follows:
175,17 → 170,19
*
* If previewing has been turned on, the score is multiplied by PRE_PENALTY.
*/
#define PRE_PENALTY 0.75
#define PRE_PENALTY 0.75
 
extern int score; /* The obvious thing */
extern int score; /* the obvious thing */
//extern gid_t gid, egid;
 
extern char key_msg[100];
extern int showpreview;
extern int classic;
extern char key_msg[100];
extern int showpreview;
extern int classic;
 
extern int fits_in(const struct shape *, int);
extern void place(const struct shape *, int, int);
extern void stop(char *);
int fits_in(const struct shape *, int);
void place(const struct shape *, int, int);
void stop(char *);
 
/** @}
*/
 
/branches/network/uspace/app/tetris/shapes.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,35 → 50,35
#include <unistd.h>
#include "tetris.h"
 
#define TL (-B_COLS - 1) /* top left */
#define TC (-B_COLS) /* top center */
#define TR (-B_COLS + 1) /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL (B_COLS - 1) /* bottom left */
#define BC B_COLS /* bottom center */
#define BR (B_COLS + 1) /* bottom right */
#define TL -B_COLS-1 /* top left */
#define TC -B_COLS /* top center */
#define TR -B_COLS+1 /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL B_COLS-1 /* bottom left */
#define BC B_COLS /* bottom center */
#define BR B_COLS+1 /* bottom right */
 
const struct shape shapes[] = {
/* 0 */ { 7, 7, { TL, TC, MR }, 0xff042d},
/* 1 */ { 8, 8, { TC, TR, ML }, 0xff9304},
/* 2 */ { 9, 11, { ML, MR, BC }, 0xbeff04},
/* 3 */ { 3, 3, { TL, TC, ML }, 0x63ff04},
/* 4 */ { 12, 14, { ML, BL, MR }, 0xce04ff},
/* 5 */ { 15, 17, { ML, BR, MR }, 0xff04cf},
/* 6 */ { 18, 18, { ML, MR, 2 }, 0x7604ff}, /* sticks out */
/* 7 */ { 0, 0, { TC, ML, BL }, 0xff042d},
/* 8 */ { 1, 1, { TC, MR, BR }, 0xff9304},
/* 9 */ { 10, 2, { TC, MR, BC }, 0xbeff04},
/* 10 */ { 11, 9, { TC, ML, MR }, 0xbeff04},
/* 11 */ { 2, 10, { TC, ML, BC }, 0xbeff04},
/* 12 */ { 13, 4, { TC, BC, BR }, 0xce04ff},
/* 13 */ { 14, 12, { TR, ML, MR }, 0xce04ff},
/* 14 */ { 4, 13, { TL, TC, BC }, 0xce04ff},
/* 15 */ { 16, 5, { TR, TC, BC }, 0xff04cf},
/* 16 */ { 17, 15, { TL, MR, ML }, 0xff04cf},
/* 17 */ { 5, 16, { TC, BC, BL }, 0xff04cf},
/* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x7604ff} /* sticks out */
/* 0*/ { 7, 7, { TL, TC, MR } },
/* 1*/ { 8, 8, { TC, TR, ML } },
/* 2*/ { 9, 11, { ML, MR, BC } },
/* 3*/ { 3, 3, { TL, TC, ML } },
/* 4*/ { 12, 14, { ML, BL, MR } },
/* 5*/ { 15, 17, { ML, BR, MR } },
/* 6*/ { 18, 18, { ML, MR, 2 } }, /* sticks out */
/* 7*/ { 0, 0, { TC, ML, BL } },
/* 8*/ { 1, 1, { TC, MR, BR } },
/* 9*/ { 10, 2, { TC, MR, BC } },
/*10*/ { 11, 9, { TC, ML, MR } },
/*11*/ { 2, 10, { TC, ML, BC } },
/*12*/ { 13, 4, { TC, BC, BR } },
/*13*/ { 14, 12, { TR, ML, MR } },
/*14*/ { 4, 13, { TL, TC, BC } },
/*15*/ { 16, 5, { TR, TC, BC } },
/*16*/ { 17, 15, { TL, MR, ML } },
/*17*/ { 5, 16, { TC, BC, BL } },
/*18*/ { 6, 6, { TC, BC, 2*B_COLS } }/* sticks out */
};
 
/*
85,14 → 85,14
* Return true iff the given shape fits in the given position,
* taking the current board into account.
*/
int fits_in(const struct shape *shape, int pos)
int
fits_in(const struct shape *shape, int pos)
{
int *o = shape->off;
if ((board[pos]) || (board[pos + *o++]) || (board[pos + *o++]) ||
(board[pos + *o]))
 
if (board[pos] || board[pos + *o++] || board[pos + *o++] ||
board[pos + *o])
return 0;
return 1;
}
 
100,15 → 100,17
* Write the given shape into the current board, turning it on
* if `onoff' is 1, and off if `onoff' is 0.
*/
void place(const struct shape *shape, int pos, int onoff)
void
place(const struct shape *shape, int pos, int onoff)
{
int *o = shape->off;
board[pos] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o] = onoff ? shape->color : 0x000000;
 
board[pos] = onoff;
board[pos + *o++] = onoff;
board[pos + *o++] = onoff;
board[pos + *o] = onoff;
}
 
/** @}
*/
 
/branches/network/uspace/app/tetris/input.h
36,14 → 36,15
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
extern int rwait(struct timeval *);
extern int tgetchar(void);
extern void tsleep(void);
int rwait(struct timeval *);
int tgetchar(void);
void tsleep(void);
 
/** @}
*/
 
/branches/network/uspace/app/tetris/pathnames.h
0,0 → 1,49
/* $OpenBSD: pathnames.h,v 1.3 2003/06/03 03:01:41 millert Exp $ */
/* $NetBSD: pathnames.h,v 1.2 1995/04/22 07:42:37 cgd Exp $ */
 
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek and Darren F. Provine.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93
*/
 
/** @addtogroup tetris
* @{
*/
/** @file
*/
 
#define _PATH_SCOREFILE "/var/games/tetris.scores"
 
 
/** @}
*/
 
/branches/network/uspace/app/klog/klog.c
40,34 → 40,41
#include <ipc/services.h>
#include <as.h>
#include <sysinfo.h>
#include <io/stream.h>
#include <console.h>
#include <event.h>
#include <errno.h>
#include <io/klog.h>
 
#define NAME "klog"
#define NAME "klog"
 
/* Pointer to klog area */
static wchar_t *klog;
static size_t klog_length;
static count_t klog_length;
 
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
size_t klog_start = (size_t) IPC_GET_ARG1(*call);
size_t klog_len = (size_t) IPC_GET_ARG2(*call);
size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
size_t i;
async_serialize_start();
count_t klog_start = (count_t) IPC_GET_ARG1(*call);
count_t klog_len = (count_t) IPC_GET_ARG2(*call);
count_t klog_stored = (count_t) IPC_GET_ARG3(*call);
count_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
putchar(klog[(klog_start + i) % klog_length]);
async_serialize_end();
}
 
int main(int argc, char *argv[])
{
size_t klog_pages = sysinfo_value("klog.pages");
console_wait();
count_t klog_pages = sysinfo_value("klog.pages");
size_t klog_size = klog_pages * PAGE_SIZE;
klog_length = klog_size / sizeof(wchar_t);
klog = (wchar_t *) as_get_mappable_page(klog_size);
klog = (wchar_t *) as_get_mappable_page(klog_pages);
if (klog == NULL) {
printf(NAME ": Error allocating memory area\n");
return -1;
/branches/network/uspace/app/klog/Makefile
64,7 → 64,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/uspace/app/trace/trace.c
41,8 → 41,6
#include <udebug.h>
#include <async.h>
#include <task.h>
#include <mem.h>
#include <string.h>
#include <loader/loader.h>
 
#include <libc.h>
663,8 → 661,11
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);
proto_add_oper(p, CONSOLE_GETKEY, o);
 
arg_def[0] = V_CHAR;
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_PUTCHAR, o);
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_CLEAR, o);
 
674,7 → 675,9
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def);
proto_add_oper(p, CONSOLE_GET_SIZE, o);
proto_add_oper(p, CONSOLE_GETSIZE, o);
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_FLUSH, o);
 
arg_def[0] = V_INTEGER;
o = oper_new("set_style", 1, arg_def, V_VOID, 0, resp_def);
/branches/network/uspace/app/trace/ipcp.c
34,7 → 34,7
 
#include <stdio.h>
#include <stdlib.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#include "ipc_desc.h"
#include "proto.h"
/branches/network/uspace/app/trace/proto.c
35,7 → 35,7
#include <stdio.h>
#include <stdlib.h>
#include <ipc/ipc.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#include "trace.h"
#include "proto.h"
/branches/network/uspace/app/trace/proto.h
35,7 → 35,7
#ifndef PROTO_H_
#define PROTO_H_
 
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <ipc/ipc.h>
#include "trace.h"
 
/branches/network/uspace/lib/libc/include/devmap.h
File deleted
/branches/network/uspace/lib/libc/include/fibril_sync.h
File deleted
/branches/network/uspace/lib/libc/include/adt/hash_table.h
File deleted
/branches/network/uspace/lib/libc/include/adt/list.h
File deleted
/branches/network/uspace/lib/libc/include/adt/fifo.h
File deleted
/branches/network/uspace/lib/libc/include/console.h
0,0 → 1,65
/*
* Copyright (c) 2008 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 libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_H_
#define LIBC_CONSOLE_H_
 
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
#include <bool.h>
 
extern int console_open(bool);
extern void console_close(void);
extern void console_wait(void);
 
extern void console_clear(void);
extern void console_goto(int, int);
extern void console_putchar(wchar_t);
extern ssize_t console_write(const char *, size_t);
extern void console_putstr(const char *);
extern void console_flush(void);
 
extern int console_get_size(int *, int *);
extern void console_set_style(int);
extern void console_set_color(int, int, int);
extern void console_set_rgb_color(int, int);
extern void console_cursor_visibility(int);
 
extern void console_kcon_enable(void);
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/string.h
39,12 → 39,13
#include <sys/types.h>
#include <bool.h>
 
#define U_SPECIAL '?'
#define U_SPECIAL '?'
#define U_BOM 0xfeff
 
/** No size limit constant */
/**< No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
 
/** Maximum size of a string containing @c length characters */
/**< Maximum size of a string containing @c length characters */
#define STR_BOUNDS(length) ((length) << 2)
 
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
53,20 → 54,20
extern size_t str_size(const char *str);
extern size_t wstr_size(const wchar_t *str);
 
extern size_t str_lsize(const char *str, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
extern size_t str_lsize(const char *str, count_t max_len);
extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
 
extern size_t str_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
 
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
extern count_t str_nlength(const char *str, size_t size);
extern count_t wstr_nlength(const wchar_t *str, size_t size);
 
extern bool ascii_check(wchar_t ch);
extern bool chr_check(wchar_t ch);
 
extern int str_cmp(const char *s1, const char *s2);
extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
77,8 → 78,8
extern const char *str_chr(const char *str, wchar_t ch);
extern const 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);
extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
extern bool wstr_remove(wchar_t *str, count_t pos);
 
extern char *str_dup(const char *);
 
/branches/network/uspace/lib/libc/include/vfs/vfs.h
36,36 → 36,12
#define LIBC_VFS_H_
 
#include <sys/types.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
#include <stdio.h>
 
/**
* This type is a libc version of the VFS triplet.
* It uniquelly identifies a file system node within a file system instance.
*/
typedef struct {
fs_handle_t fs_handle;
dev_handle_t dev_handle;
fs_index_t index;
} fdi_node_t;
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *, const char *,
unsigned int);
const unsigned int flags);
 
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);
extern int fd_node(int, fdi_node_t *);
 
extern FILE *fopen_node(fdi_node_t *, const char *);
extern int fphone(FILE *);
extern int fnode(FILE *, fdi_node_t *);
 
#endif
 
/** @}
/branches/network/uspace/lib/libc/include/async.h
44,15 → 44,12
typedef ipc_callid_t aid_t;
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
 
extern atomic_t async_futex;
 
static inline void async_manager(void)
{
fibril_switch(FIBRIL_TO_MANAGER);
}
 
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
 
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)
{
return async_get_call_timeout(data, 0);
66,19 → 63,19
*/
 
#define async_send_0(phoneid, method, dataptr) \
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
#define async_send_1(phoneid, method, arg1, dataptr) \
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
#define async_send_2(phoneid, method, arg1, arg2, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
 
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
89,12 → 86,12
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
suseconds_t timeout);
 
extern fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
extern void async_usleep(suseconds_t timeout);
extern void async_create_manager(void);
extern void async_destroy_manager(void);
extern int _async_init(void);
void async_usleep(suseconds_t timeout);
void async_create_manager(void);
void async_destroy_manager(void);
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);
101,22 → 98,22
 
/* Wrappers for simple communication */
#define async_msg_0(phone, method) \
ipc_call_async_0((phone), (method), NULL, NULL, true)
ipc_call_async_0((phone), (method), NULL, NULL, true)
#define async_msg_1(phone, method, arg1) \
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
true)
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
true)
#define async_msg_2(phone, method, arg1, arg2) \
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
#define async_msg_3(phone, method, arg1, arg2, arg3) \
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, true)
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, true)
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, true)
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, true)
 
/*
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
125,90 → 122,90
* and slow verion based on m.
*/
#define async_req_0_0(phoneid, method) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
#define async_req_0_1(phoneid, method, r1) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
#define async_req_0_2(phoneid, method, r1, r2) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
#define async_req_0_3(phoneid, method, r1, r2, r3) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
#define async_req_1_0(phoneid, method, arg1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
#define async_req_1_1(phoneid, method, arg1, rc1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
#define async_req_2_0(phoneid, method, arg1, arg2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), (rc5))
#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
218,14 → 215,14
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(rc1), (rc2), (rc3), (rc4), (rc5))
#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
rc3) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
256,6 → 253,8
fibril_dec_sercount();
}
 
extern atomic_t async_futex;
 
#endif
 
/** @}
/branches/network/uspace/lib/libc/include/stdio.h
37,117 → 37,78
 
#include <sys/types.h>
#include <stdarg.h>
#include <adt/list.h>
 
#define EOF (-1)
#define EOF (-1)
 
/** Default size for stream I/O buffers */
#define BUFSIZ 4096
#include <string.h>
#include <io/stream.h>
 
#define DEBUG(fmt, ...) \
{ \
char buf[256]; \
int n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \
int n; \
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
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
enum _buffer_type {
/** No buffering */
_IONBF,
/** Line buffering */
_IOLBF,
/** Full buffering */
_IOFBF
};
 
typedef struct {
/** Linked list pointer. */
link_t link;
/** Underlying file descriptor. */
int fd;
 
/** Error indicator. */
int error;
 
/** End-of-file indicator. */
int eof;
/** Klog indicator */
int klog;
/** Phone to the file provider */
int phone;
 
/** Buffering type */
enum _buffer_type btype;
/** Buffer */
uint8_t *buf;
/** Buffer size */
size_t buf_size;
/** Buffer I/O pointer */
uint8_t *buf_head;
} FILE;
 
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
extern FILE *stdin, *stdout, *stderr;
 
/* Character and string input functions */
extern int fgetc(FILE *);
extern char *fgets(char *, size_t, FILE *);
 
extern int getchar(void);
extern char *gets(char *, size_t);
 
/* Character and string output functions */
extern int fputc(wchar_t, FILE *);
extern int fputs(const char *, FILE *);
 
extern int putchar(wchar_t);
extern int puts(const char *);
extern int putchar(int);
extern int fflush(FILE *);
 
/* Formatted string output functions */
extern int fprintf(FILE *, const char*, ...);
extern int vfprintf(FILE *, const char *, va_list);
extern int printf(const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int printf(const char *, ...);
extern int vprintf(const char *, va_list);
 
extern int snprintf(char *, size_t , const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
/* File stream functions */
extern int rename(const char *, const char *);
 
extern FILE *fopen(const char *, const char *);
extern FILE *fdopen(int, const char *);
extern int fclose(FILE *);
 
extern size_t fread(void *, size_t, size_t, FILE *);
extern size_t fwrite(const void *, size_t, size_t, FILE *);
 
extern int fseek(FILE *, long, int);
extern void rewind(FILE *);
extern int ftell(FILE *);
extern int feof(FILE *);
 
extern int fflush(FILE *);
extern int ferror(FILE *);
extern void clearerr(FILE *);
 
extern void setvbuf(FILE *, void *, int, size_t);
extern int fgetc(FILE *);
extern int fputc(int, FILE *);
extern int fputs(const char *, FILE *);
 
/* Misc file functions */
extern int rename(const char *, const char *);
extern int fprintf(FILE *, const char *, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
#define getc fgetc
#define putc fputc
 
extern int fseek(FILE *, long, int);
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/io/keycode.h
File deleted
/branches/network/uspace/lib/libc/include/io/color.h
File deleted
/branches/network/uspace/lib/libc/include/io/console.h
File deleted
/branches/network/uspace/lib/libc/include/io/klog.h
File deleted
/branches/network/uspace/lib/libc/include/io/style.h
File deleted
/branches/network/uspace/lib/libc/include/io/stream.h
0,0 → 1,48
/*
* Copyright (c) 2006 Jakub Vana
* 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_STREAM_H_
#define LIBC_STREAM_H_
 
#include <libarch/types.h>
 
#define EMFILE -17
 
extern ssize_t read_stdin(void *, size_t);
extern void klog_update(void);
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/io/printf_core.h
56,3 → 56,5
 
/** @}
*/
/branches/network/uspace/lib/libc/include/io/io.h
0,0 → 1,50
/*
* Copyright (c) 2006 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.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_H_
#define LIBC_IO_H_
 
#include <sys/types.h>
 
int putnchars(const char * buf, size_t count);
int putstr(const char * str);
int putchar(int c);
int getchar(void);
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/ipc/vfs.h
File deleted
/branches/network/uspace/lib/libc/include/ipc/bd.h
File deleted
/branches/network/uspace/lib/libc/include/ipc/console.h
27,7 → 27,7
*/
 
/** @addtogroup libcipc
* @{
* @{
*/
/** @file
*/
36,13 → 36,15
#define LIBC_IPC_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <ipc/vfs.h>
 
typedef enum {
CONSOLE_GET_SIZE = VFS_LAST_SRV,
CONSOLE_GET_EVENT,
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
CONSOLE_PUTCHAR,
CONSOLE_WRITE,
CONSOLE_CLEAR,
CONSOLE_GOTO,
CONSOLE_CLEAR,
CONSOLE_GETSIZE,
CONSOLE_FLUSH,
CONSOLE_SET_STYLE,
CONSOLE_SET_COLOR,
CONSOLE_SET_RGB_COLOR,
51,6 → 53,6
} console_request_t;
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/ipc/ipc.h
30,26 → 30,21
* @{
*/
/** @file
*/
*/
 
#ifndef LIBIPC_IPC_H_
#define LIBIPC_IPC_H_
 
#include <task.h>
#include <kernel/ipc/ipc.h>
#include <kernel/ddi/irq.h>
#include <sys/types.h>
#include <kernel/synch/synch.h>
 
#define IPC_FLAG_BLOCKING 0x01
 
typedef sysarg_t ipcarg_t;
 
typedef struct {
ipcarg_t args[IPC_CALL_LEN];
ipcarg_t in_phone_hash;
} ipc_call_t;
 
typedef sysarg_t ipc_callid_t;
 
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *);
61,51 → 56,49
* possible, the fast version is used.
*/
#define ipc_call_sync_0_0(phoneid, method) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_0_1(phoneid, method, res1) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_0_2(phoneid, method, res1, res2) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
#define ipc_call_sync_0_3(phoneid, method, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
#define ipc_call_sync_0_4(phoneid, method, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
#define ipc_call_sync_0_5(phoneid, method, res1, res2, res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
 
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
#define ipc_call_sync_1_0(phoneid, method, arg1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_1_2(phoneid, method, arg1, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
#define ipc_call_sync_1_3(phoneid, method, arg1, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
#define ipc_call_sync_1_4(phoneid, method, arg1, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
#define ipc_call_sync_1_5(phoneid, method, arg1, res1, res2, res3, res4, \
res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), (res5))
 
#define ipc_call_sync_2_0(phoneid, method, arg1, arg2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
#define ipc_call_sync_2_1(phoneid, method, arg1, arg2, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
#define ipc_call_sync_2_2(phoneid, method, arg1, arg2, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_2_3(phoneid, method, arg1, arg2, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
#define ipc_call_sync_2_4(phoneid, method, arg1, arg2, res1, res2, res3, \
res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
114,16 → 107,15
res4, res5)\
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), (res4), (res5))
 
#define ipc_call_sync_3_0(phoneid, method, arg1, arg2, arg3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
#define ipc_call_sync_3_1(phoneid, method, arg1, arg2, arg3, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
#define ipc_call_sync_3_2(phoneid, method, arg1, arg2, arg3, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_3_3(phoneid, method, arg1, arg2, arg3, res1, res2, \
res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
136,16 → 128,15
res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
(res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
res3) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
158,13 → 149,12
res3, res4, res5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
(arg4), 0, (res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
#define ipc_call_sync_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
#define ipc_call_sync_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
191,12 → 181,10
 
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int);
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t);
 
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
{
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
}
 
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *);
 
/*
206,17 → 194,17
* to m.
*/
#define ipc_answer_0(callid, retval) \
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
#define ipc_answer_1(callid, retval, arg1) \
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
#define ipc_answer_2(callid, retval, arg1, arg2) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
 
extern ipcarg_t ipc_answer_fast(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t);
258,6 → 246,8
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int);
 
#define IPC_FLAG_BLOCKING 0x01
 
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *);
extern int ipc_connect_me_to(int, int, int, int);
extern int ipc_connect_me_to_blocking(int, int, int, int);
266,19 → 256,20
extern int ipc_unregister_irq(int, int);
extern int ipc_forward_fast(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, int);
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, ipcarg_t, int);
ipcarg_t, ipcarg_t, ipcarg_t, int);
 
 
/*
* User-friendly wrappers for ipc_share_in_start().
*/
#define ipc_share_in_start_0_0(phoneid, dst, size) \
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
#define ipc_share_in_start_0_1(phoneid, dst, size, flags) \
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
#define ipc_share_in_start_1_0(phoneid, dst, size, arg) \
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
293,6 → 284,8
extern int ipc_data_write_receive(ipc_callid_t *, size_t *);
extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
 
#include <task.h>
 
extern int ipc_connect_kbox(task_id_t);
 
#endif
/branches/network/uspace/lib/libc/include/ipc/loader.h
42,7 → 42,6
LOADER_GET_TASKID,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_SET_FILES,
LOADER_LOAD,
LOADER_RUN
} loader_request_t;
/branches/network/uspace/lib/libc/include/ipc/devmap.h
33,14 → 33,11
#ifndef DEVMAP_DEVMAP_H_
#define DEVMAP_DEVMAP_H_
 
#include <atomic.h>
#include <ipc/ipc.h>
#include <adt/list.h>
#include <libadt/list.h>
 
#define DEVMAP_NAME_MAXLEN 255
#define DEVMAP_NAME_MAXLEN 512
 
typedef ipcarg_t dev_handle_t;
 
typedef enum {
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
DEVMAP_DRIVER_UNREGISTER,
47,30 → 44,56
DEVMAP_DEVICE_REGISTER,
DEVMAP_DEVICE_UNREGISTER,
DEVMAP_DEVICE_GET_NAME,
DEVMAP_DEVICE_GET_HANDLE,
DEVMAP_DEVICE_GET_COUNT,
DEVMAP_DEVICE_GET_DEVICES
DEVMAP_DEVICE_GET_HANDLE
} devmap_request_t;
 
/** Interface provided by devmap.
/** Representation of device driver.
* Each driver is responsible for a set of devices.
*/
typedef struct {
/** Pointers to previous and next drivers in linked list */
link_t drivers;
/** Pointer to the linked list of devices controlled by
* this driver */
link_t devices;
/** Phone asociated with this driver */
ipcarg_t phone;
/** Device driver name */
char *name;
/** Futex for list of devices owned by this driver */
atomic_t devices_futex;
} devmap_driver_t;
 
/** Info about registered device
*
*/
typedef struct {
/** Pointer to the previous and next device in the list of all devices */
link_t devices;
/** Pointer to the previous and next device in the list of devices
owned by one driver */
link_t driver_devices;
/** Unique device identifier */
int handle;
/** Device name */
char *name;
/** Device driver handling this device */
devmap_driver_t *driver;
} devmap_device_t;
 
/** Interface provided by devmap.
* Every process that connects to devmap must ask one of following
* interfaces otherwise connection will be refused.
*
*/
typedef enum {
/** Connect as device driver */
DEVMAP_DRIVER = 1,
/** Connect as client */
/** Connect as device driver */
DEVMAP_DRIVER = 1,
/** Connect as client */
DEVMAP_CLIENT,
/** Create new connection to instance of device that
is specified by second argument of call. */
/** Create new connection to instance of device that
* is specified by second argument of call. */
DEVMAP_CONNECT_TO_DEVICE
} devmap_interface_t;
 
typedef struct {
dev_handle_t handle;
char name[DEVMAP_NAME_MAXLEN + 1];
} dev_desc_t;
#endif
 
#endif
/branches/network/uspace/lib/libc/include/ipc/ns.h
35,13 → 35,6
#ifndef LIBIPC_NS_H_
#define LIBIPC_NS_H_
 
#include <ipc/ipc.h>
 
typedef enum {
NS_PING = IPC_FIRST_USER_METHOD,
NS_TASK_WAIT
} ns_request_t;
 
#endif
 
/** @}
/branches/network/uspace/lib/libc/include/unistd.h
39,30 → 39,26
#include <libarch/config.h>
 
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
 
#define getpagesize() (PAGE_SIZE)
#define getpagesize() (PAGE_SIZE)
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
extern ssize_t write(int, const void *, size_t);
extern ssize_t read(int, void *, size_t);
 
extern off_t lseek(int, off_t, int);
extern int ftruncate(int, off_t);
 
extern int close(int);
extern int fsync(int);
extern int unlink(const char *);
 
extern char *getcwd(char *buf, size_t);
extern int rmdir(const char *);
extern int chdir(const char *);
extern char *getcwd(char *buf, size_t);
 
extern void _exit(int status) __attribute__ ((noreturn));
extern void *sbrk(ssize_t incr);
/branches/network/uspace/lib/libc/include/kbd/kbd.h
0,0 → 1,65
/*
* 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 libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_H_
#define LIBC_KBD_H_
 
#include <sys/types.h>
 
typedef enum kbd_ev_type {
KE_PRESS,
KE_RELEASE
} kbd_ev_type_t;
 
/** Keyboard event structure. */
typedef struct {
/** Press or release event. */
kbd_ev_type_t type;
 
/** Keycode of the key that was pressed or released. */
unsigned int key;
 
/** Bitmask of modifiers held. */
unsigned int mods;
 
/** The character that was generated or '\0' for none. */
wchar_t c;
} kbd_event_t;
 
extern int kbd_get_event(kbd_event_t *);
 
#endif
/** @}
*/
/branches/network/uspace/lib/libc/include/kbd/keycode.h
0,0 → 1,220
/*
* 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 libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_KEYCODE_H_
#define LIBC_KBD_KEYCODE_H_
 
/** Keycode definitions.
*
* A keycode identifies a key by its position on the keyboard, rather
* than by its label. For human readability, key positions are noted
* with the key label on a keyboard with US layout. This label has
* nothing to do with the character, that the key produces
* -- this is determined by the keymap.
*
* The keyboard model reflects a standard PC keyboard layout.
* Non-standard keyboards need to be mapped to this model in some
* logical way. Scancodes are mapped to keycodes with a scanmap.
*
* For easier mapping to the model and to emphasize the nature of keycodes,
* they really are organized here by position, rather than by label.
*/
enum keycode {
 
/* Main block row 1 */
 
KC_BACKTICK = 1,
 
KC_1,
KC_2,
KC_3,
KC_4,
KC_5,
KC_6,
KC_7,
KC_8,
KC_9,
KC_0,
 
KC_MINUS,
KC_EQUALS,
KC_BACKSPACE,
 
/* Main block row 2 */
 
KC_TAB,
 
KC_Q,
KC_W,
KC_E,
KC_R,
KC_T,
KC_Y,
KC_U,
KC_I,
KC_O,
KC_P,
 
KC_LBRACKET,
KC_RBRACKET,
 
/* Main block row 3 */
 
KC_CAPS_LOCK,
KC_A,
KC_S,
KC_D,
KC_F,
KC_G,
KC_H,
KC_J,
KC_K,
KC_L,
 
KC_SEMICOLON,
KC_QUOTE,
KC_BACKSLASH,
 
KC_ENTER,
 
/* Main block row 4 */
 
KC_LSHIFT,
 
KC_Z,
KC_X,
KC_C,
KC_V,
KC_B,
KC_N,
KC_M,
 
KC_COMMA,
KC_PERIOD,
KC_SLASH,
 
KC_RSHIFT,
 
/* Main block row 5 */
 
KC_LCTRL,
KC_LALT,
KC_SPACE,
KC_RALT,
KC_RCTRL,
 
/* Function keys block */
 
KC_ESCAPE,
 
KC_F1,
KC_F2,
KC_F3,
KC_F4,
KC_F5,
KC_F6,
KC_F7,
KC_F8,
KC_F9,
KC_F10,
KC_F11,
KC_F12,
 
KC_PRTSCR,
KC_SCROLL_LOCK,
KC_PAUSE,
 
/* Cursor keys block */
 
KC_INSERT,
KC_HOME,
KC_PAGE_UP,
 
KC_DELETE,
KC_END,
KC_PAGE_DOWN,
 
KC_UP,
KC_LEFT,
KC_DOWN,
KC_RIGHT,
 
/* Numeric block */
 
KC_NUM_LOCK,
KC_NSLASH,
KC_NTIMES,
KC_NMINUS,
 
KC_NPLUS,
KC_NENTER,
 
KC_N7,
KC_N8,
KC_N9,
 
KC_N4,
KC_N5,
KC_N6,
 
KC_N1,
KC_N2,
KC_N3,
 
KC_N0,
KC_NPERIOD
} keycode_t;
 
enum keymod {
KM_LSHIFT = 0x001,
KM_RSHIFT = 0x002,
KM_LCTRL = 0x004,
KM_RCTRL = 0x008,
KM_LALT = 0x010,
KM_RALT = 0x020,
KM_CAPS_LOCK = 0x040,
KM_NUM_LOCK = 0x080,
KM_SCROLL_LOCK = 0x100,
 
KM_SHIFT = KM_LSHIFT | KM_RSHIFT,
KM_CTRL = KM_LCTRL | KM_RCTRL,
KM_ALT = KM_LALT | KM_RALT
} keymod_t;
 
#endif
/** @}
*/
/branches/network/uspace/lib/libc/include/byteorder.h
35,47 → 35,48
#ifndef LIBC_BYTEORDER_H_
#define LIBC_BYTEORDER_H_
 
#include <libarch/byteorder.h>
#include <stdint.h>
 
#if !(defined(__BE__) ^ defined(__LE__))
#error The architecture must be either big-endian or little-endian.
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN))
#error The architecture must be either big-endian or little-endian.
#endif
 
#ifdef __BE__
#ifdef ARCH_IS_BIG_ENDIAN
 
#define uint16_t_le2host(n) (uint16_t_byteorder_swap(n))
#define uint32_t_le2host(n) (uint32_t_byteorder_swap(n))
#define uint64_t_le2host(n) (uint64_t_byteorder_swap(n))
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n)
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n)
 
#define uint16_t_be2host(n) (n)
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
#define uint16_t_be2host(n) (n)
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
 
#define host2uint16_t_le(n) (uint16_t_byteorder_swap(n))
#define host2uint32_t_le(n) (uint32_t_byteorder_swap(n))
#define host2uint64_t_le(n) (uint64_t_byteorder_swap(n))
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
 
#else
 
#define uint16_t_le2host(n) (n)
#define uint32_t_le2host(n) (n)
#define uint64_t_le2host(n) (n)
#define uint16_t_le2host(n) (n)
#define uint32_t_le2host(n) (n)
#define uint64_t_le2host(n) (n)
 
#define uint16_t_be2host(n) (uint16_t_byteorder_swap(n))
#define uint32_t_be2host(n) (uint32_t_byteorder_swap(n))
#define uint64_t_be2host(n) (uint64_t_byteorder_swap(n))
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n)
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
 
#define host2uint16_t_be(n) (uint16_t_byteorder_swap(n))
#define host2uint32_t_be(n) (uint32_t_byteorder_swap(n))
#define host2uint64_t_be(n) (uint64_t_byteorder_swap(n))
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n)
 
#endif
 
/branches/network/uspace/lib/libc/include/task.h
42,7 → 42,6
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);
 
#endif
 
/branches/network/uspace/lib/libc/include/console/color.h
0,0 → 1,55
/*
* Copyright (c) 2008 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 libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_COLOR_H_
#define LIBC_CONSOLE_COLOR_H_
 
enum console_color {
COLOR_BLACK = 0,
COLOR_BLUE = 1,
COLOR_GREEN = 2,
COLOR_CYAN = 3,
COLOR_RED = 4,
COLOR_MAGENTA = 5,
COLOR_YELLOW = 6,
COLOR_WHITE = 7,
 
CATTR_BRIGHT = 8,
CATTR_BLINK = 8
};
 
#endif
/** @}
*/
/branches/network/uspace/lib/libc/include/console/style.h
0,0 → 1,46
/*
* Copyright (c) 2008 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 libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_STYLE_H_
#define LIBC_CONSOLE_STYLE_H_
 
enum console_style {
STYLE_NORMAL = 0,
STYLE_EMPHASIS = 1
};
 
#endif
/** @}
*/
/branches/network/uspace/lib/libc/include/loader/pcb.h
37,7 → 37,6
#define LIBC_PCB_H_
 
#include <sys/types.h>
#include <vfs/vfs.h>
 
typedef void (*entry_point_t)(void);
 
46,26 → 45,19
* Holds pointers to data passed from the program loader to the program
* and/or to the dynamic linker. This includes the program entry point,
* arguments, environment variables etc.
*
*/
typedef struct {
/** Program entry point. */
entry_point_t entry;
 
/** Number of command-line arguments. */
int argc;
/** Command-line arguments. */
char **argv;
/** Number of preset files. */
int filc;
/** Preset files. */
fdi_node_t **filv;
 
/*
* ELF-specific data.
*/
/** Pointer to ELF dynamic section of the program. */
void *dynamic;
} pcb_t;
/branches/network/uspace/lib/libc/include/loader/loader.h
37,7 → 37,6
#define LIBC_LOADER_H_
 
#include <task.h>
#include <vfs/vfs.h>
 
/** Abstraction of a loader connection */
typedef struct {
49,8 → 48,7
extern loader_t *loader_connect(void);
extern int loader_get_task_id(loader_t *, task_id_t *);
extern int loader_set_pathname(loader_t *, const char *);
extern int loader_set_args(loader_t *, char *const[]);
extern int loader_set_files(loader_t *, fdi_node_t *const[]);
extern int loader_set_args(loader_t *, char *const []);
extern int loader_load_program(loader_t *);
extern int loader_run(loader_t *);
extern void loader_abort(loader_t *);
/branches/network/uspace/lib/libc/include/macros.h
35,22 → 35,15
#ifndef LIBC_MACROS_H_
#define LIBC_MACROS_H_
 
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#define LOWER32(arg) ((arg) & 0xffffffff)
#define UPPER32(arg) (((arg) >> 32) & 0xffffffff)
 
#define MERGE_LOUP32(lo, up) \
((((uint64_t) (lo)) & 0xffffffff) \
| ((((uint64_t) (up)) & 0xffffffff) << 32))
 
#endif
 
/** @}
/branches/network/uspace/lib/libc/include/errno.h
41,18 → 41,17
 
#include <kernel/errno.h>
 
#define EMFILE (-17)
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#endif
 
/branches/network/uspace/lib/libc/include/libadt/list.h
0,0 → 1,206
/*
* Copyright (c) 2001-2004 Jakub Jermar
* 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_LIST_H_
#define LIBC_LIST_H_
 
#include <unistd.h>
 
#ifndef true
# define true 1
#endif
#ifndef false
# define false 0
#endif
 
typedef struct link link_t;
 
/** Doubly linked list head and link type. */
struct link {
link_t *prev; /**< Pointer to the previous item in the list. */
link_t *next; /**< Pointer to the next item in the list. */
};
 
/** Declare and initialize statically allocated list.
*
* @param name Name of the new statically allocated list.
*/
#define LIST_INITIALIZE(name) link_t name = { .prev = &name, .next = &name }
 
/** Initialize doubly-linked circular list link
*
* Initialize doubly-linked list link.
*
* @param link Pointer to link_t structure to be initialized.
*/
static inline void link_initialize(link_t *link)
{
link->prev = NULL;
link->next = NULL;
}
 
/** Initialize doubly-linked circular list
*
* Initialize doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_initialize(link_t *head)
{
head->prev = head;
head->next = head;
}
 
/** Add item to the beginning of doubly-linked circular list
*
* Add item to the beginning of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_prepend(link_t *link, link_t *head)
{
link->next = head->next;
link->prev = head;
head->next->prev = link;
head->next = link;
}
 
/** Add item to the end of doubly-linked circular list
*
* Add item to the end of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_append(link_t *link, link_t *head)
{
link->prev = head->prev;
link->next = head;
head->prev->next = link;
head->prev = link;
}
 
/** Insert item before another item in doubly-linked circular list. */
static inline void list_insert_before(link_t *l, link_t *r)
{
list_append(l, r);
}
 
/** Insert item after another item in doubly-linked circular list. */
static inline void list_insert_after(link_t *r, link_t *l)
{
list_prepend(l, r);
}
 
/** Remove item from doubly-linked circular list
*
* Remove item from doubly-linked circular list.
*
* @param link Pointer to link_t structure to be removed from the list it is contained in.
*/
static inline void list_remove(link_t *link)
{
link->next->prev = link->prev;
link->prev->next = link->next;
link_initialize(link);
}
 
/** Query emptiness of doubly-linked circular list
*
* Query emptiness of doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline int list_empty(link_t *head)
{
return head->next == head ? true : false;
}
 
 
/** Split or concatenate headless doubly-linked circular list
*
* Split or concatenate headless doubly-linked circular list.
*
* Note that the algorithm works both directions:
* concatenates splitted lists and splits concatenated lists.
*
* @param part1 Pointer to link_t structure leading the first (half of the headless) list.
* @param part2 Pointer to link_t structure leading the second (half of the headless) list.
*/
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
{
link_t *hlp;
 
part1->prev->next = part2;
part2->prev->next = part1;
hlp = part1->prev;
part1->prev = part2->prev;
part2->prev = hlp;
}
 
 
/** Split headless doubly-linked circular list
*
* Split headless doubly-linked circular list.
*
* @param part1 Pointer to link_t structure leading the first half of the headless list.
* @param part2 Pointer to link_t structure leading the second half of the headless list.
*/
static inline void headless_list_split(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
/** Concatenate two headless doubly-linked circular lists
*
* Concatenate two headless doubly-linked circular lists.
*
* @param part1 Pointer to link_t structure leading the first headless list.
* @param part2 Pointer to link_t structure leading the second headless list.
*/
static inline void headless_list_concat(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
#define list_get_instance(link,type,member) (type *)(((char *)(link))-((char *)&(((type *)NULL)->member)))
 
extern int list_member(const link_t *link, const link_t *head);
extern void list_concat(link_t *head1, link_t *head2);
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/libadt/hash_table.h
0,0 → 1,94
/*
* Copyright (c) 2006 Jakub Jermar
* 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_HASH_TABLE_H_
#define LIBC_HASH_TABLE_H_
 
#include <libadt/list.h>
#include <unistd.h>
 
typedef unsigned long hash_count_t;
typedef unsigned long hash_index_t;
typedef struct hash_table hash_table_t;
typedef struct hash_table_operations hash_table_operations_t;
 
/** Hash table structure. */
struct hash_table {
link_t *entry;
hash_count_t entries;
hash_count_t max_keys;
hash_table_operations_t *op;
};
 
/** Set of operations for hash table. */
struct hash_table_operations {
/** Hash function.
*
* @param key Array of keys needed to compute hash index. All keys
* must be passed.
*
* @return Index into hash table.
*/
hash_index_t (* hash)(unsigned long key[]);
/** Hash table item comparison function.
*
* @param key Array of keys that will be compared with item. It is
* not necessary to pass all keys.
*
* @return true if the keys match, false otherwise.
*/
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
* @param item Item that was removed from the hash table.
*/
void (*remove_callback)(link_t *item);
};
 
#define hash_table_get_instance(item, type, member) \
list_get_instance((item), type, member)
 
extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
hash_table_operations_t *);
extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
extern link_t *hash_table_find(hash_table_t *, unsigned long []);
extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
extern void hash_table_destroy(hash_table_t *);
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/libadt/fifo.h
0,0 → 1,127
/*
* Copyright (c) 2006 Jakub Jermar
* 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
*/
 
/*
* This implementation of FIFO stores values in an array
* (static or dynamic). As such, these FIFOs have upper bound
* on number of values they can store. Push and pop operations
* are done via accessing the array through head and tail indices.
* Because of better operation ordering in fifo_pop(), the access
* policy for these two indices is to 'increment (mod size of FIFO)
* and use'.
*/
 
#ifndef LIBC_FIFO_H_
#define LIBC_FIFO_H_
 
#include <malloc.h>
 
typedef unsigned long fifo_count_t;
typedef unsigned long fifo_index_t;
 
#define FIFO_CREATE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name
 
/** Create and initialize static FIFO.
*
* FIFO is allocated statically.
* This macro is suitable for creating smaller FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
FIFO_CREATE_STATIC(name, t, itms) = { \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Create and prepare dynamic FIFO.
*
* FIFO is allocated dynamically.
* This macro is suitable for creating larger FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Pop value from head of FIFO.
*
* @param name FIFO name.
*
* @return Leading value in FIFO.
*/
#define fifo_pop(name) \
name.fifo[name.head = (name.head + 1) < name.items ? (name.head + 1) : 0]
 
/** Push value to tail of FIFO.
*
* @param name FIFO name.
* @param value Value to be appended to FIFO.
*
*/
#define fifo_push(name, value) \
name.fifo[name.tail = (name.tail + 1) < name.items ? (name.tail + 1) : 0] = (value)
 
/** Allocate memory for dynamic FIFO.
*
* @param name FIFO name.
*/
#define fifo_create(name) \
name.fifo = malloc(sizeof(*name.fifo) * name.items)
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/include/fcntl.h
35,13 → 35,13
#ifndef LIBC_FCNTL_H_
#define LIBC_FCNTL_H_
 
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
 
extern int open(const char *, int, ...);
 
/branches/network/uspace/lib/libc/include/dirent.h
35,7 → 35,7
#ifndef LIBC_DIRENT_H_
#define LIBC_DIRENT_H_
 
#define NAME_MAX 256
#define NAME_MAX 256
 
struct dirent {
char d_name[NAME_MAX + 1];
46,6 → 46,7
struct dirent res;
} DIR;
 
 
extern DIR *opendir(const char *);
extern struct dirent *readdir(DIR *);
extern void rewinddir(DIR *);
/branches/network/uspace/lib/libc/include/fibril.h
36,18 → 36,17
#define LIBC_FIBRIL_H_
 
#include <libarch/fibril.h>
#include <adt/list.h>
#include <libadt/list.h>
#include <libarch/tls.h>
 
#ifndef context_set
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#endif /* context_set */
 
#define FIBRIL_SERIALIZED 1
#define FIBRIL_WRITER 2
#define FIBRIL_SERIALIZED 1
 
typedef enum {
FIBRIL_PREEMPT,
72,9 → 71,6
};
typedef struct fibril fibril_t;
 
/** Fibril-local variable specifier */
#define fibril_local __thread
 
extern int context_save(context_t *c);
extern void context_restore(context_t *c) __attribute__ ((noreturn));
 
/branches/network/uspace/lib/libc/generic/devmap.c
File deleted
/branches/network/uspace/lib/libc/generic/adt/hash_table.c
File deleted
/branches/network/uspace/lib/libc/generic/adt/list.c
File deleted
/branches/network/uspace/lib/libc/generic/fibril_sync.c
File deleted
/branches/network/uspace/lib/libc/generic/kbd.c
0,0 → 1,62
/*
* 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 libc
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <io/stream.h>
#include <kbd/kbd.h>
#include <ipc/ipc.h>
#include <ipc/console.h>
#include <console.h>
#include <async.h>
 
int kbd_get_event(kbd_event_t *ev)
{
int cons_phone = console_open(true);
ipcarg_t r0, r1, r2, r3;
int rc;
 
rc = async_req_0_4(cons_phone, CONSOLE_GETKEY, &r0, &r1, &r2, &r3);
if (rc < 0)
return -1;
 
ev->type = r0;
ev->key = r1;
ev->mods = r2;
ev->c = r3;
 
return 0;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/console.c
0,0 → 1,274
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* Copyright (c) 2008 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 libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <async.h>
#include <io/stream.h>
#include <ipc/console.h>
#include <ipc/services.h>
#include <errno.h>
#include <string.h>
#include <console.h>
 
static int console_phone = -1;
 
/** Size of cbuffer. */
#define CBUFFER_SIZE 256
 
/** Buffer for writing characters to the console. */
static char cbuffer[CBUFFER_SIZE];
 
/** Pointer to end of cbuffer. */
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
 
/** Pointer to first available field in cbuffer. */
static char *cbp = cbuffer;
 
 
/** Write one character to the console via IPC. */
static void cons_putchar(wchar_t c)
{
console_wait();
async_msg_1(console_phone, CONSOLE_PUTCHAR, c);
}
 
/** Write characters to the console via IPC or to klog */
static ssize_t cons_write(const char *buf, size_t size)
{
console_open(false);
if (console_phone >= 0) {
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer);
ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return (ssize_t) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
if (rc == EOK)
return (ssize_t) IPC_GET_ARG1(answer);
else
return -1;
} else
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
}
 
/** Write all data from output buffer to the console. */
static void cbuffer_flush(void)
{
size_t len = cbp - cbuffer;
while (len > 0) {
ssize_t rc = cons_write(cbuffer, cbp - cbuffer);
if (rc < 0)
return;
len -= rc;
}
cbp = cbuffer;
}
 
/** Drop all data in console output buffer. */
static void cbuffer_drain(void)
{
cbp = cbuffer;
}
 
/** Write one character to the output buffer. */
static inline void cbuffer_putc(char c)
{
if (cbp == cbuffer_end)
cbuffer_flush();
*cbp++ = c;
if (c == '\n')
cbuffer_flush();
}
 
int console_open(bool blocking)
{
if (console_phone < 0) {
int phone;
if (blocking)
phone = ipc_connect_me_to_blocking(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
else
phone = ipc_connect_me_to(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
if (phone >= 0)
console_phone = phone;
}
return console_phone;
}
 
void console_close(void)
{
if (console_phone >= 0) {
if (ipc_hangup(console_phone) == 0)
console_phone = -1;
}
}
 
void console_wait(void)
{
while (console_phone < 0)
console_open(true);
}
 
void console_clear(void)
{
console_wait();
cbuffer_drain();
async_msg_0(console_phone, CONSOLE_CLEAR);
}
 
int console_get_size(int *rows, int *cols)
{
console_wait();
ipcarg_t r;
ipcarg_t c;
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c);
*rows = (int) r;
*cols = (int) c;
return rc;
}
 
void console_set_style(int style)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int fg_color, int bg_color, int flags)
{
console_wait();
cbuffer_flush();
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int fg_color, int bg_color)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int show)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
}
 
void console_kcon_enable(void)
{
console_wait();
cbuffer_flush();
async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
}
 
void console_goto(int row, int col)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_GOTO, row, col);
}
 
void console_putchar(wchar_t c)
{
console_wait();
cbuffer_flush();
cons_putchar(c);
}
 
/** Write characters to the console. */
ssize_t console_write(const char *buf, size_t size)
{
size_t left = size;
while (left > 0) {
cbuffer_putc(*buf++);
left--;
}
return size;
}
 
/** Write a NULL-terminated string to the console. */
void console_putstr(const char *str)
{
size_t left = str_size(str);
while (left > 0) {
ssize_t rc = console_write(str, left);
if (rc < 0) {
/* Error */
return;
}
str += rc;
left -= rc;
}
}
 
/** Flush all output to the console or klog. */
void console_flush(void)
{
cbuffer_flush();
if (console_phone >= 0)
async_msg_0(console_phone, CONSOLE_FLUSH);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/string.c
138,8 → 138,8
* @param size Size of the output buffer (in bytes).
*
* @return EOK if the character was encoded successfully, EOVERFLOW if there
* was not enough space in the output buffer or EINVAL if the character
* code was invalid.
* was not enough space in the output buffer or EINVAL if the character
* code was invalid.
*/
int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
{
243,9 → 243,9
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, size_t max_len)
size_t str_lsize(const char *str, count_t max_len)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (len < max_len) {
271,7 → 271,7
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, size_t max_len)
size_t wstr_lsize(const wchar_t *str, count_t max_len)
{
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
283,9 → 283,9
* @return Number of characters in string.
*
*/
size_t str_length(const char *str)
count_t str_length(const char *str)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
301,9 → 301,9
* @return Number of characters in @a str.
*
*/
size_t wstr_length(const wchar_t *wstr)
count_t wstr_length(const wchar_t *wstr)
{
size_t len = 0;
count_t len = 0;
while (*wstr++ != 0)
len++;
319,9 → 319,9
* @return Number of characters in string.
*
*/
size_t str_nlength(const char *str, size_t size)
count_t str_nlength(const char *str, size_t size)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
338,11 → 338,11
* @return Number of characters in string.
*
*/
size_t wstr_nlength(const wchar_t *str, size_t size)
count_t wstr_nlength(const wchar_t *str, size_t size)
{
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
430,7 → 430,7
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, size_t max_len)
int str_lcmp(const char *s1, const char *s2, count_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
438,7 → 438,7
size_t off1 = 0;
size_t off2 = 0;
size_t len = 0;
count_t len = 0;
 
while (true) {
if (len >= max_len)
568,7 → 568,7
return;
wchar_t ch;
size_t src_idx = 0;
count_t src_idx = 0;
size_t dst_off = 0;
while ((ch = src[src_idx++]) != 0) {
616,7 → 616,7
wchar_t acc;
size_t off = 0;
size_t last = 0;
const char *res = NULL;
char *res = NULL;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
641,14 → 641,14
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
size_t i;
count_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
669,14 → 669,14
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, size_t pos)
bool wstr_remove(wchar_t *str, count_t pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if (pos >= len)
return false;
size_t i;
count_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
/branches/network/uspace/lib/libc/generic/loader.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <ipc/ipc.h>
#include <ipc/loader.h>
47,12 → 47,9
/** Connect to a new program loader.
*
* Spawns a new program loader task and returns the connection structure.
*
* @param name Symbolic name to set on the newly created task.
*
* @return Pointer to the loader connection structure (should be
* deallocated using free() after use).
*
* @param name Symbolic name to set on the newly created task.
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*/
int loader_spawn(const char *name)
{
62,16 → 59,19
 
loader_t *loader_connect(void)
{
int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
loader_t *ldr;
int phone_id;
 
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
loader_t *ldr = malloc(sizeof(loader_t));
 
ldr = malloc(sizeof(loader_t));
if (ldr == NULL)
return NULL;
 
ldr->phone_id = phone_id;
return ldr;
return ldr;
}
 
/** Get ID of the new task.
78,26 → 78,27
*
* Retrieves the ID of the new task from the loader.
*
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
* @return Zero on success or negative error code.
*/
int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
{
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
/* Get task ID. */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
ipcarg_t retval;
 
async_wait_for(req, &retval);
return (int) retval;
return (int)retval;
}
 
/** Set pathname of the program to load.
106,35 → 107,39
* to the current working directory (it will be absolutized before
* sending to the loader).
*
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
* @return Zero on success or negative error code.
*/
int loader_set_pathname(loader_t *ldr, const char *path)
{
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
char *pa = absolutize(path, &pa_len);
 
pa = absolutize(path, &pa_len);
if (!pa)
return 0;
 
/* Send program pathname */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
free(pa);
ipcarg_t retval;
 
async_wait_for(req, &retval);
return (int) retval;
return (int)retval;
}
 
 
/** Set command-line arguments for the program.
*
* Sets the vector of command-line arguments to be passed to the loaded
141,110 → 146,61
* program. By convention, the very first argument is typically the same as
* the command used to execute the program.
*
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
* @return Zero on success or negative error code.
*/
int loader_set_args(loader_t *ldr, char *const argv[])
{
/*
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
char *const *ap;
char *dp;
char *arg_buf;
size_t buffer_size;
 
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
char *const *ap = argv;
size_t buffer_size = 0;
ap = argv;
buffer_size = 0;
while (*ap != NULL) {
buffer_size += str_size(*ap) + 1;
ap++;
++ap;
}
char *arg_buf = malloc(buffer_size);
if (arg_buf == NULL)
return ENOMEM;
 
arg_buf = malloc(buffer_size);
if (arg_buf == NULL) return ENOMEM;
 
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
char *dp = arg_buf;
dp = arg_buf;
 
while (*ap != NULL) {
str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
dp += str_size(*ap) + 1;
ap++;
 
++ap;
}
 
/* Send serialized arguments to the loader */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
 
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
async_wait_for(req, &rc);
if (rc != EOK)
return rc;
if (rc != EOK) return rc;
 
/* Free temporary buffer */
free(arg_buf);
return EOK;
}
 
/** Set preset files for the program.
*
* Sets the vector of preset files to be passed to the loaded
* program. By convention, the first three files represent stdin,
* stdout and stderr respectively.
*
* @param ldr Loader connection structure.
* @param files NULL-terminated array of pointers to files.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
{
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
fdi_node_t *const *ap = files;
size_t count = 0;
while (*ap != NULL) {
count++;
ap++;
}
fdi_node_t *files_buf;
files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
if (files_buf == NULL)
return ENOMEM;
/* Fill the buffer */
size_t i;
for (i = 0; i < count; i++)
files_buf[i] = *files[i];
/* Send serialized files to the loader */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
count * sizeof(fdi_node_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
async_wait_for(req, &rc);
if (rc != EOK)
return rc;
/* Free temporary buffer */
free(files_buf);
return EOK;
}
 
253,14 → 209,18
* If this function succeeds, the program has been successfully loaded
* and is ready to be executed.
*
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
*/
int loader_load_program(loader_t *ldr)
{
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
if (rc != EOK)
return rc;
 
return EOK;
}
 
/** Instruct loader to execute the program.
272,17 → 232,17
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
*/
int loader_run(loader_t *ldr)
{
int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
if (rc != EOK)
return rc;
 
ipc_hangup(ldr->phone_id);
ldr->phone_id = 0;
return EOK;
294,10 → 254,8
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
*/
void loader_abort(loader_t *ldr)
{
/branches/network/uspace/lib/libc/generic/libc.c
27,29 → 27,28
*/
 
/** @addtogroup lc Libc
* @brief HelenOS C library
* @brief HelenOS C library
* @{
* @}
*/
 
/** @addtogroup libc generic
* @ingroup lc
* @{
*/
 
/** @file
*/
*/
 
#include <libc.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <tls.h>
#include <thread.h>
#include <fibril.h>
#include <io/stream.h>
#include <ipc/ipc.h>
#include <async.h>
#include <as.h>
#include <console.h>
#include <loader/pcb.h>
 
extern char _heap;
64,30 → 63,28
 
void __main(void *pcb_ptr)
{
fibril_t *f;
int argc;
char **argv;
 
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
fibril_t *fibril = fibril_setup();
__tcb_set(fibril->tcb);
f = fibril_setup();
__tcb_set(f->tcb);
/* Save the PCB pointer */
__pcb = (pcb_t *) pcb_ptr;
int argc;
char **argv;
__pcb = (pcb_t *)pcb_ptr;
 
if (__pcb == NULL) {
argc = 0;
argv = NULL;
stdio_init(0, NULL);
} else {
argc = __pcb->argc;
argv = __pcb->argv;
stdio_init(__pcb->filc, __pcb->filv);
}
 
main(argc, argv);
stdio_done();
console_flush();
}
 
void __exit(void)
/branches/network/uspace/lib/libc/generic/async.c
95,8 → 95,8
#include <async.h>
#include <fibril.h>
#include <stdio.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <ipc/ipc.h>
#include <assert.h>
#include <errno.h>
174,7 → 174,7
} connection_t;
 
/** Identifier of the incoming connection handled by the current fibril. */
fibril_local connection_t *FIBRIL_connection;
__thread connection_t *FIBRIL_connection;
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
190,9 → 190,11
*/
static async_client_conn_t interrupt_received = default_interrupt_received;
 
 
static hash_table_t conn_hash_table;
static LIST_INITIALIZE(timeout_list);
 
 
#define CONN_HASH_TABLE_CHAINS 32
 
/** Compute hash into the connection hash table based on the source phone hash.
498,10 → 500,9
/* Answer all remaining messages with EHANGUP */
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg_t *msg;
msg_t *msg
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link);
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
list_remove(&msg->link);
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
562,7 → 563,7
}
/* Add connection to the connection hash table */
unsigned long key = conn->in_phone_hash;
ipcarg_t key = conn->in_phone_hash;
futex_down(&async_futex);
hash_table_insert(&conn_hash_table, &key, &conn->link);
587,28 → 588,23
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
process_notification(callid, call);
goto out;
return;
}
switch (IPC_GET_METHOD(*call)) {
case IPC_M_CONNECT_ME:
case IPC_M_CONNECT_ME_TO:
/* Open new connection with fibril etc. */
async_new_connection(IPC_GET_ARG5(*call), callid, call,
client_connection);
goto out;
return;
}
/* Try to route the call through the connection hash table */
if (route_call(callid, call))
goto out;
return;
/* Unknown call from unknown phone - hang it up */
ipc_answer_0(callid, EHANGUP);
return;
out:
;
}
 
/** Fire all timeouts that expired. */
666,8 → 662,8
suseconds_t timeout;
if (!list_empty(&timeout_list)) {
awaiter_t *waiter = list_get_instance(timeout_list.next,
awaiter_t, link);
awaiter_t *waiter
= list_get_instance(timeout_list.next, awaiter_t, link);
struct timeval tv;
gettimeofday(&tv, NULL);
684,8 → 680,8
futex_up(&async_futex);
ipc_call_t call;
ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
SYNCH_FLAGS_NONE);
ipc_callid_t callid
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE);
if (!callid) {
handle_expired_timeouts();
762,13 → 758,13
*/
static void reply_received(void *arg, int retval, ipc_call_t *data)
{
futex_down(&async_futex);
amsg_t *msg = (amsg_t *) arg;
msg->retval = retval;
futex_down(&async_futex);
/* Copy data after futex_down, just in case the call was detached */
if ((msg->dataptr) && (data))
if (msg->dataptr)
*msg->dataptr = *data;
write_barrier();
814,7 → 810,6
msg->done = false;
msg->dataptr = dataptr;
msg->wdata.inlist = false;
/* We may sleep in the next method, but it will use its own mechanism */
msg->wdata.active = true;
854,7 → 849,6
msg->done = false;
msg->dataptr = dataptr;
msg->wdata.inlist = false;
/* We may sleep in next method, but it will use its own mechanism */
msg->wdata.active = true;
/branches/network/uspace/lib/libc/generic/vfs/vfs.c
48,14 → 48,13
#include <futex.h>
#include <errno.h>
#include <string.h>
#include <devmap.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
#include "../../../srv/vfs/vfs.h"
 
static int vfs_phone = -1;
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static futex_t cwd_futex = FUTEX_INITIALIZER;
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
 
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_size = 0;
116,8 → 115,47
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
}
 
static int device_get_handle(const char *name, dev_handle_t *handle,
const unsigned int flags)
{
int phone;
if (flags & IPC_FLAG_BLOCKING)
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
else
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
if (phone < 0)
return phone;
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
&answer);
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
if (retval != EOK) {
async_wait_for(req, NULL);
ipc_hangup(phone);
return retval;
}
async_wait_for(req, &retval);
if (handle != NULL)
*handle = -1;
if (retval == EOK) {
if (handle != NULL)
*handle = (dev_handle_t) IPC_GET_ARG1(answer);
}
ipc_hangup(phone);
return retval;
}
 
int mount(const char *fs_name, const char *mp, const char *dev,
const char *opts, unsigned int flags)
const char *opts, const unsigned int flags)
{
int res;
ipcarg_t rc;
124,7 → 162,7
aid_t req;
dev_handle_t dev_handle;
res = devmap_device_get_handle(dev, &dev_handle, flags);
res = device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
211,10 → 249,9
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
 
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
223,27 → 260,6
return _open(path, L_FILE, oflag);
}
 
int open_node(fdi_node_t *node, int oflag)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipc_call_t answer;
aid_t req = async_send_4(vfs_phone, VFS_OPEN_NODE, node->fs_handle,
node->dev_handle, node->index, oflag, &answer);
ipcarg_t rc;
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
int close(int fildes)
{
ipcarg_t rc;
314,62 → 330,6
return -1;
}
 
int fd_phone(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);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return -1;
return devmap_device_connect((dev_handle_t) device, 0);
}
 
int fd_node(int fildes, fdi_node_t *node)
{
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);
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;
}
return rc;
}
 
int fsync(int fildes)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_SYNC, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
}
 
off_t lseek(int fildes, off_t offset, int whence)
{
ipcarg_t rc;
465,7 → 425,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
static int _unlink(const char *path, int lflag)
495,7 → 455,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
int unlink(const char *path)
/branches/network/uspace/lib/libc/generic/io/klog.c
File deleted
/branches/network/uspace/lib/libc/generic/io/console.c
File deleted
/branches/network/uspace/lib/libc/generic/io/io.c
30,551 → 30,98
* @{
*/
/** @file
*/
*/
 
#include <libc.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <io/io.h>
#include <string.h>
#include <errno.h>
#include <bool.h>
#include <malloc.h>
#include <io/klog.h>
#include <vfs/vfs.h>
#include <ipc/devmap.h>
#include <adt/list.h>
#include <console.h>
 
static void _fflushbuf(FILE *stream);
const static char nl = '\n';
 
static FILE stdin_null = {
.fd = -1,
.error = true,
.eof = true,
.klog = false,
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
static FILE stdout_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1,
.btype = _IOLBF,
.buf = NULL,
.buf_size = BUFSIZ,
.buf_head = NULL
};
 
static FILE stderr_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
FILE *stdin = NULL;
FILE *stdout = NULL;
FILE *stderr = NULL;
 
static LIST_INITIALIZE(files);
 
void stdio_init(int filc, fdi_node_t *filv[])
int puts(const char *str)
{
if (filc > 0) {
stdin = fopen_node(filv[0], "r");
} else {
stdin = &stdin_null;
list_append(&stdin->link, &files);
}
size_t count;
if (filc > 1) {
stdout = fopen_node(filv[1], "w");
} else {
stdout = &stdout_klog;
list_append(&stdout->link, &files);
}
if (str == NULL)
return putnchars("(NULL)", 6);
if (filc > 2) {
stderr = fopen_node(filv[2], "w");
} else {
stderr = &stderr_klog;
list_append(&stderr->link, &files);
}
}
 
void stdio_done(void)
{
link_t *link = files.next;
for (count = 0; str[count] != 0; count++);
while (link != &files) {
FILE *file = list_get_instance(link, FILE, link);
fclose(file);
link = files.next;
if (console_write((void *) str, count) == count) {
if (console_write(&nl, 1) == 1)
return 0;
}
}
 
static bool parse_mode(const char *mode, int *flags)
{
/* Parse mode except first character. */
const char *mp = mode;
if (*mp++ == 0) {
errno = EINVAL;
return false;
}
if ((*mp == 'b') || (*mp == 't'))
mp++;
bool plus;
if (*mp == '+') {
mp++;
plus = true;
} else
plus = false;
if (*mp != 0) {
errno = EINVAL;
return false;
}
/* Parse first character of mode and determine flags for open(). */
switch (mode[0]) {
case 'r':
*flags = plus ? O_RDWR : O_RDONLY;
break;
case 'w':
*flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
break;
case 'a':
/* TODO: a+ must read from beginning, append to the end. */
if (plus) {
errno = ENOTSUP;
return false;
}
*flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return false;
}
return true;
return EOF;
}
 
/** Set stream buffer. */
void setvbuf(FILE *stream, void *buf, int mode, size_t size)
{
stream->btype = mode;
stream->buf = buf;
stream->buf_size = size;
stream->buf_head = stream->buf;
}
 
/** Allocate stream buffer. */
static int _fallocbuf(FILE *stream)
{
assert(stream->buf == NULL);
 
stream->buf = malloc(stream->buf_size);
if (stream->buf == NULL) {
errno = ENOMEM;
return -1;
}
 
stream->buf_head = stream->buf;
return 0;
}
 
/** Open a stream.
*
* @param path Path of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*
/** Put count chars from buffer to stdout without adding newline
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
* @param count
* @return 0 on succes, EOF on fail
*/
FILE *fopen(const char *path, const char *mode)
int putnchars(const char *buf, size_t count)
{
int flags;
if (!parse_mode(mode, &flags))
return NULL;
if (console_write((void *) buf, count) == count)
return 0;
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open(path, flags, 0666);
if (stream->fd < 0) {
/* errno was set by open() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOFBF, BUFSIZ);
list_append(&stream->link, &files);
return stream;
return EOF;
}
 
FILE *fdopen(int fd, const char *mode)
{
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = fd;
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
list_append(&stream->link, &files);
return stream;
}
 
FILE *fopen_node(fdi_node_t *node, const char *mode)
{
int flags;
if (!parse_mode(mode, &flags))
return NULL;
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open_node(node, flags);
if (stream->fd < 0) {
/* errno was set by open_node() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
list_append(&stream->link, &files);
return stream;
}
 
int fclose(FILE *stream)
{
int rc = 0;
fflush(stream);
if (stream->phone >= 0)
ipc_hangup(stream->phone);
if (stream->fd >= 0)
rc = close(stream->fd);
list_remove(&stream->link);
if ((stream != &stdin_null)
&& (stream != &stdout_klog)
&& (stream != &stderr_klog))
free(stream);
stream = NULL;
if (rc != 0) {
/* errno was set by close() */
return EOF;
}
return 0;
}
 
/** Read from a stream.
/** Same as puts, but does not print newline at end
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param stream Pointer to the stream.
*
*/
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
int putstr(const char *str)
{
size_t left = size * nmemb;
size_t done = 0;
 
/* Make sure no data is pending write. */
_fflushbuf(stream);
 
while ((left > 0) && (!stream->error) && (!stream->eof)) {
ssize_t rd = read(stream->fd, buf + done, left);
if (rd < 0)
stream->error = true;
else if (rd == 0)
stream->eof = true;
else {
left -= rd;
done += rd;
}
}
size_t count;
return (done / size);
}
if (str == NULL)
return putnchars("(NULL)", 6);
 
static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
size_t left = size * nmemb;
size_t done = 0;
for (count = 0; str[count] != 0; count++);
if (console_write((void *) str, count) == count)
return 0;
while ((left > 0) && (!stream->error)) {
ssize_t wr;
if (stream->klog)
wr = klog_write(buf + done, left);
else
wr = write(stream->fd, buf + done, left);
if (wr <= 0)
stream->error = true;
else {
left -= wr;
done += wr;
}
}
return (done / size);
return EOF;
}
 
/** Drain stream buffer, do not sync stream. */
static void _fflushbuf(FILE *stream)
int putchar(int c)
{
size_t bytes_used;
char buf[STR_BOUNDS(1)];
size_t offs;
 
if (!stream->buf || stream->btype == _IONBF || stream->error)
return;
offs = 0;
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
return EOF;
 
bytes_used = stream->buf_head - stream->buf;
if (bytes_used == 0)
return;
if (console_write((void *) buf, offs) == offs)
return c;
 
(void) _fwrite(stream->buf, 1, bytes_used, stream);
stream->buf_head = stream->buf;
return EOF;
}
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param stream Pointer to the stream.
*
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
int getchar(void)
{
uint8_t *data;
size_t bytes_left;
size_t now;
size_t buf_free;
size_t total_written;
size_t i;
uint8_t b;
bool need_flush;
 
/* If not buffered stream, write out directly. */
if (stream->btype == _IONBF)
return _fwrite(buf, size, nmemb, stream);
 
/* Perform lazy allocation of stream buffer. */
if (stream->buf == NULL) {
if (_fallocbuf(stream) != 0)
return 0; /* Errno set by _fallocbuf(). */
}
 
data = (uint8_t *) buf;
bytes_left = size * nmemb;
total_written = 0;
need_flush = false;
 
while (!stream->error && bytes_left > 0) {
 
buf_free = stream->buf_size - (stream->buf_head - stream->buf);
if (bytes_left > buf_free)
now = buf_free;
else
now = bytes_left;
 
for (i = 0; i < now; i++) {
b = data[i];
stream->buf_head[i] = b;
 
if (b == '\n' && stream->btype == _IOLBF)
need_flush = true;
}
 
buf += now;
stream->buf_head += now;
buf_free -= now;
bytes_left -= now;
total_written += now;
 
if (buf_free == 0) {
/* Only need to drain buffer. */
_fflushbuf(stream);
need_flush = false;
}
}
 
if (need_flush)
fflush(stream);
 
return (total_written / size);
}
 
int fputc(wchar_t c, FILE *stream)
{
char buf[STR_BOUNDS(1)];
size_t sz = 0;
unsigned char c;
if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
size_t wr = fwrite(buf, sz, 1, stream);
if (wr < sz)
return EOF;
return (int) c;
}
console_flush();
if (read_stdin((void *) &c, 1) == 1)
return c;
return EOF;
}
 
int putchar(wchar_t c)
int fflush(FILE *f)
{
return fputc(c, stdout);
}
 
int fputs(const char *str, FILE *stream)
{
return fwrite(str, str_size(str), 1, stream);
}
 
int puts(const char *str)
{
return fputs(str, stdout);
}
 
int fgetc(FILE *stream)
{
char c;
 
/* This could be made faster by only flushing when needed. */
if (stdout)
fflush(stdout);
if (stderr)
fflush(stderr);
 
if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
return EOF;
return (int) c;
}
 
int getchar(void)
{
return fgetc(stdin);
}
 
int fseek(FILE *stream, long offset, int origin)
{
off_t rc = lseek(stream->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
stream->eof = false;
/* Dummy implementation */
(void) f;
console_flush();
return 0;
}
 
void rewind(FILE *stream)
{
(void) fseek(stream, 0, SEEK_SET);
}
 
int fflush(FILE *stream)
{
_fflushbuf(stream);
 
if (stream->klog) {
klog_update();
return EOK;
}
if (stream->fd >= 0)
return fsync(stream->fd);
return ENOENT;
}
 
int feof(FILE *stream)
{
return stream->eof;
}
 
int ferror(FILE *stream)
{
return stream->error;
}
 
int fphone(FILE *stream)
{
if (stream->fd >= 0) {
if (stream->phone < 0)
stream->phone = fd_phone(stream->fd);
return stream->phone;
}
return -1;
}
 
int fnode(FILE *stream, fdi_node_t *node)
{
if (stream->fd >= 0)
return fd_node(stream->fd, node);
return ENOENT;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/vprintf.c
38,25 → 38,37
#include <io/printf_core.h>
#include <futex.h>
#include <async.h>
#include <string.h>
#include <console.h>
 
static atomic_t printf_futex = FUTEX_INITIALIZER;
 
static int vprintf_str_write(const char *str, size_t size, void *stream)
static int vprintf_str_write(const char *str, size_t size, void *data)
{
size_t wr = fwrite(str, 1, size, (FILE *) stream);
return str_nlength(str, wr);
size_t offset = 0;
size_t prev;
count_t chars = 0;
while (offset < size) {
prev = offset;
str_decode(str, &offset, size);
console_write(str + prev, offset - prev);
chars++;
}
return chars;
}
 
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream)
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
{
size_t offset = 0;
size_t chars = 0;
size_t boff;
count_t chars = 0;
char buf[4];
while (offset < size) {
if (fputc(str[chars], (FILE *) stream) <= 0)
break;
boff = 0;
chr_encode(str[chars], buf, &boff, 4);
console_write(buf, boff);
chars++;
offset += sizeof(wchar_t);
}
64,55 → 76,33
return chars;
}
 
 
/** Print formatted text.
*
* @param stream Output stream
* @param fmt Format string
* @param ap Format parameters
*
* @param fmt format string
* @param ap format parameters
* \see For more details about format string see printf_core.
*
*/
int vfprintf(FILE *stream, const char *fmt, va_list ap)
int vprintf(const char *fmt, va_list ap)
{
struct printf_spec ps = {
vprintf_str_write,
vprintf_wstr_write,
stream
NULL
};
/*
* Prevent other threads to execute printf_core()
*/
futex_down(&printf_futex);
/*
* Prevent other fibrils of the same thread
* Prevent other pseudo threads of the same thread
* to execute printf_core()
*/
async_serialize_start();
int ret = printf_core(fmt, &ps, ap);
async_serialize_end();
futex_up(&printf_futex);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param file Output stream
* @param fmt Format string
* @param ap Format parameters
*
* \see For more details about format string see printf_core.
*
*/
int vprintf(const char *fmt, va_list ap)
{
return vfprintf(stdout, fmt, ap);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/stream.c
0,0 → 1,80
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* 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 <io/io.h>
#include <io/stream.h>
#include <string.h>
#include <malloc.h>
#include <libc.h>
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
#include <unistd.h>
#include <async.h>
#include <sys/types.h>
 
ssize_t read_stdin(void *buf, size_t count)
{
int cons_phone = console_open(false);
if (cons_phone >= 0) {
kbd_event_t ev;
int rc;
size_t i = 0;
while (i < count) {
do {
rc = kbd_get_event(&ev);
if (rc < 0) return -1;
} while (ev.c == 0 || ev.type == KE_RELEASE);
((char *) buf)[i++] = ev.c;
}
return i;
} else
return -1;
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/fprintf.c
0,0 → 1,77
/*
* Copyright (c) 2008 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 libc
* @{
*/
/**
* @file
* @brief fprintf, vfprintf
*/
 
#include <stdio.h>
#include <sys/types.h>
#include <io/printf_core.h>
 
static int vfprintf_str_write(const char *s, size_t size, void *f)
{
/* FIXME: Should return number of characters? */
return fwrite(s, 1, size, (FILE *) f);
}
 
static int vfprintf_wstr_write(const char *s, size_t size, void *f)
{
/* TODO */
return size;
}
 
int vfprintf(FILE *f, const char *fmt, va_list ap)
{
struct printf_spec ps = {
vfprintf_str_write,
vfprintf_wstr_write,
(void *) f
};
 
return printf_core(fmt, &ps, ap);
}
 
int fprintf(FILE *f, const char *fmt, ...)
{
int rv;
va_list args;
 
va_start(args, fmt);
rv = vfprintf(f, fmt, args);
va_end(args);
 
return rv;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/vsnprintf.c
82,7 → 82,7
* with the trailing zero => print only a part
* of string
*/
size_t index = 0;
index_t index = 0;
while (index < size) {
wchar_t uc = str_decode(str, &index, size);
130,7 → 130,7
*/
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
size_t index = 0;
index_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
/branches/network/uspace/lib/libc/generic/io/printf_core.c
173,7 → 173,7
*/
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
211,7 → 211,7
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
254,12 → 254,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
size_t strw = str_length(str);
count_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
301,6 → 301,9
if (str == NULL)
return printf_putstr(nullstr, ps);
if (*str == U_BOM)
str++;
/* Print leading spaces. */
size_t strw = wstr_length(str);
if (precision == 0)
307,7 → 310,7
precision = strw;
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
429,7 → 432,7
}
width -= precision + size - number_size;
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
592,7 → 595,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
size_t counter = 0; /* Number of characters printed */
count_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/network/uspace/lib/libc/generic/io/stdio.c
0,0 → 1,278
/*
* Copyright (c) 2008 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 libc
* @{
*/
/**
* @file
* @brief ANSI C Stream I/O.
*/
 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <bool.h>
#include <stdio.h>
 
FILE *stdin, *stdout, *stderr;
 
/**
* Open a stream.
*
* @param file_name Name of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*/
FILE *fopen(const char *file_name, const char *mode)
{
FILE *f;
int flags;
bool plus;
const char *mp;
 
/* Parse mode except first character. */
 
mp = mode;
if (*mp++ == '\0') {
errno = EINVAL;
return NULL;
}
 
if (*mp == 'b' || *mp == 't') ++mp;
 
if (*mp == '+') {
++mp;
plus = true;
} else {
plus = false;
}
 
if (*mp != '\0') {
errno = EINVAL;
return NULL;
}
 
/* Parse first character of mode and determine flags for open(). */
 
switch (mode[0]) {
case 'r':
flags = plus ? O_RDWR : O_RDONLY;
break;
case 'w':
flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
break;
case 'a':
/* TODO: a+ must read from beginning, append to the end. */
if (plus) {
errno = ENOTSUP;
return NULL;
}
flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return NULL;
}
 
/* Open file. */
f = malloc(sizeof(FILE));
if (f == NULL) {
errno = ENOMEM;
return NULL;
}
 
f->fd = open(file_name, flags, 0666);
if (f->fd < 0) {
free(f);
return NULL; /* errno was set by open() */
}
 
f->error = 0;
f->eof = 0;
 
return f;
}
 
/** Close a stream.
*
* @param f Pointer to stream.
* @return 0 on success, EOF on error.
*/
int fclose(FILE *f)
{
int rc;
 
rc = close(f->fd);
free(f);
 
if (rc != 0)
return EOF; /* errno was set by close() */
 
return 0;
}
 
/** Read from a stream.
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param f Pointer to the stream.
*/
size_t fread(void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error && !f->eof) {
n = read(f->fd, buf + done, left);
 
if (n < 0) {
f->error = 1;
} else if (n == 0) {
f->eof = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param f Pointer to the stream.
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error) {
n = write(f->fd, buf + done, left);
 
if (n <= 0) {
f->error = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
/** Return the end-of-file indicator of a stream. */
int feof(FILE *f)
{
return f->eof;
}
 
/** Return the error indicator of a stream. */
int ferror(FILE *f)
{
return f->error;
}
 
/** Clear the error and end-of-file indicators of a stream. */
void clearerr(FILE *f)
{
f->eof = 0;
f->error = 0;
}
 
/** Read character from a stream. */
int fgetc(FILE *f)
{
unsigned char c;
size_t n;
 
n = fread(&c, sizeof(c), 1, f);
if (n < 1) return EOF;
 
return (int) c;
}
 
/** Write character to a stream. */
int fputc(int c, FILE *f)
{
unsigned char cc;
size_t n;
 
cc = (unsigned char) c;
n = fwrite(&cc, sizeof(cc), 1, f);
if (n < 1) return EOF;
 
return (int) cc;
}
 
/** Write string to a stream. */
int fputs(const char *s, FILE *f)
{
int rc;
 
rc = 0;
 
while (*s && rc >= 0) {
rc = fputc(*s++, f);
}
 
if (rc < 0) return EOF;
 
return 0;
}
 
/** Seek to position in stream. */
int fseek(FILE *f, long offset, int origin)
{
off_t rc;
 
rc = lseek(f->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
 
f->eof = 0;
 
return 0;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/asprintf.c
36,52 → 36,42
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/printf_core.h>
 
static int asprintf_str_write(const char *str, size_t count, void *unused)
static int asprintf_prewrite(const char *str, size_t count, void *unused)
{
return str_nlength(str, count);
return count;
}
 
static int asprintf_wstr_write(const wchar_t *str, size_t count, void *unused)
{
return wstr_nlength(str, count);
}
 
/** Allocate and print to string.
*
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format string.
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
*
* @return Number of characters printed or a negative error code.
*
* @return Number of characters printed or a negative error code.
*/
int asprintf(char **strp, const char *fmt, ...)
{
struct printf_spec ps = {
asprintf_str_write,
asprintf_wstr_write,
NULL
asprintf_prewrite,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
int ret = printf_core(fmt, &ps, args);
ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(STR_BOUNDS(ret) + 1);
if (*strp == NULL)
*strp = malloc(ret + 20);
if (!*strp)
return -1;
va_start(args, fmt);
vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args);
va_end(args);
vsprintf(*strp, fmt, args);
va_end(args);
}
 
return ret;
}
 
/branches/network/uspace/lib/libc/generic/io/sprintf.c
0,0 → 1,57
/*
* Copyright (c) 2006 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.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <io/printf_core.h>
 
/** Print formatted to the given buffer.
* @param str buffer
* @param fmt format string
* \see For more details about format string see printf_core.
*/
int sprintf(char *str, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
ret = vsprintf(str, fmt, args);
va_end(args);
 
return ret;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/printf.c
34,43 → 34,23
 
#include <io/printf_core.h>
#include <stdio.h>
#include <stdio.h>
 
/** Print formatted text.
*
* @param stream Output stream
* @param fmt Format string
*
* @param fmt format string
* \see For more details about format string see printf_core.
*
*/
int fprintf(FILE *stream, const char *fmt, ...)
int printf(const char *fmt, ...)
{
int ret;
va_list args;
 
va_start(args, fmt);
 
ret = vprintf(fmt, args);
int ret = vfprintf(stream, fmt, args);
va_end(args);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vprintf(fmt, args);
va_end(args);
return ret;
}
 
/branches/network/uspace/lib/libc/generic/io/vsprintf.c
0,0 → 1,51
/*
* Copyright (c) 2006 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.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <io/printf_core.h>
 
/** Print formatted to the given buffer.
* @param str buffer
* @param fmt format string
* @param ap argument list
* \see For more details about format string see printf_core.
*/
int vsprintf(char *str, const char *fmt, va_list ap)
{
return vsnprintf(str, (size_t) - 1, fmt, ap);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/snprintf.c
37,23 → 37,21
#include <io/printf_core.h>
 
/** Print formatted to the given buffer with limited size.
*
* @param str Buffer
* @param size Buffer size
* @param fmt Format string
*
* @param str buffer
* @param size buffer size
* @param fmt format string
* \see For more details about format string see printf_core.
*
*/
int snprintf(char *str, size_t size, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
int ret = vsnprintf(str, size, fmt, args);
ret = vsnprintf(str, size, fmt, args);
 
va_end(args);
 
return ret;
}
 
/branches/network/uspace/lib/libc/generic/task.c
31,7 → 31,7
* @{
*/
/** @file
*/
*/
 
#include <task.h>
#include <libc.h>
39,25 → 39,21
#include <errno.h>
#include <loader/loader.h>
#include <string.h>
#include <ipc/ns.h>
#include <macros.h>
#include <async.h>
 
task_id_t task_get_id(void)
{
task_id_t task_id;
 
(void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id);
 
return task_id;
}
 
/** Set the task name.
*
* @param name The new name, typically the command used to execute the
* program.
*
* @return Zero on success or negative error code.
*
* @param name The new name, typically the command used to execute the
* program.
* @return Zero on success or negative error code.
*/
int task_set_name(const char *name)
{
69,89 → 65,58
* This is really just a convenience wrapper over the more complicated
* loader API.
*
* @param path pathname of the binary to execute
* @param argv command-line arguments
*
* @return ID of the newly created task or zero on error.
*
* @param path pathname of the binary to execute
* @param argv command-line arguments
* @return ID of the newly created task or zero on error.
*/
task_id_t task_spawn(const char *path, char *const args[])
task_id_t task_spawn(const char *path, char *const argv[])
{
loader_t *ldr;
task_id_t task_id;
int rc;
 
/* Connect to a program loader. */
loader_t *ldr = loader_connect();
ldr = loader_connect();
if (ldr == NULL)
return 0;
 
/* Get task ID. */
task_id_t task_id;
int rc = loader_get_task_id(ldr, &task_id);
rc = loader_get_task_id(ldr, &task_id);
if (rc != EOK)
goto error;
 
/* Send program pathname. */
rc = loader_set_pathname(ldr, path);
if (rc != EOK)
goto error;
 
/* Send arguments. */
rc = loader_set_args(ldr, args);
rc = loader_set_args(ldr, argv);
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)
goto error;
 
/* Run it. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
 
/* Success */
 
free(ldr);
return task_id;
 
/* Error exit */
error:
/* Error exit */
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
int task_wait(task_id_t id)
{
return (int) async_req_2_0(PHONE_NS, NS_TASK_WAIT, LOWER32(id), UPPER32(id));
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/ddi.c
127,10 → 127,10
}
#endif
 
phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
offset = pio_addr - phys;
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
virt = as_get_mappable_page(pages << PAGE_WIDTH);
virt = as_get_mappable_page(pages);
*use_addr = virt + offset;
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
}
/branches/network/uspace/lib/libc/generic/ipc.c
43,7 → 43,7
#include <libc.h>
#include <malloc.h>
#include <errno.h>
#include <adt/list.h>
#include <libadt/list.h>
#include <stdio.h>
#include <unistd.h>
#include <futex.h>
232,7 → 232,7
return;
}
 
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (callid == IPC_CALLRET_FATAL) {
futex_up(&ipc_futex);
/* Call asynchronous handler with error code */
if (call->callback)
241,7 → 241,7
return;
}
 
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == IPC_CALLRET_TEMPORARY) {
futex_up(&ipc_futex);
 
call->u.msg.phoneid = phoneid;
309,7 → 309,7
callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1,
arg2, arg3, arg4);
 
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == IPC_CALLRET_TEMPORARY) {
if (!call) {
call = ipc_prepare_async(private, callback);
if (!call)
442,7 → 442,7
call = list_get_instance(queued_calls.next, async_call_t, list);
callid = _ipc_call_async(call->u.msg.phoneid,
&call->u.msg.data);
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == IPC_CALLRET_TEMPORARY) {
break;
}
list_remove(&call->list);
451,7 → 451,7
if (call->fid)
fibril_add_ready(call->fid);
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (callid == IPC_CALLRET_FATAL) {
if (call->callback)
call->callback(call->private, ENOENT, NULL);
free(call);
704,7 → 704,7
IPC_SET_ARG4(data, arg4);
IPC_SET_ARG5(data, arg5);
 
return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode);
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode);
}
 
/** Wrapper for making IPC_M_SHARE_IN calls.
/branches/network/uspace/lib/libc/generic/mem.c
95,7 → 95,7
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
{
size_t i, j;
int i, j;
struct along *adst = dst;
const struct along *asrc = src;
 
/branches/network/uspace/lib/libc/generic/as.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <as.h>
#include <libc.h>
102,7 → 102,7
static size_t heapsize = 0;
static size_t maxheapsize = (size_t) (-1);
 
static void *last_allocated = 0;
static void * last_allocated = 0;
 
/* Start of heap linker symbol */
extern char _heap;
119,15 → 119,15
void *res;
/* Check for invalid values */
if ((incr < 0) && (((size_t) -incr) > heapsize))
if (incr < 0 && -incr > heapsize)
return NULL;
/* Check for too large value */
if ((incr > 0) && (incr + heapsize < heapsize))
if (incr > 0 && incr+heapsize < heapsize)
return NULL;
/* Check for too small values */
if ((incr < 0) && (incr + heapsize > heapsize))
if (incr < 0 && incr+heapsize > heapsize)
return NULL;
/* Check for user limit */
175,7 → 175,7
asz = 1 << (fnzb64(sz - 1) + 1);
 
/* Set heapsize to some meaningful value */
if (maxheapsize == (size_t) -1)
if (maxheapsize == -1)
set_maxheapsize(MAX_HEAP_SIZE);
/*
/branches/network/uspace/lib/libc/generic/fibril.c
33,7 → 33,7
/** @file
*/
 
#include <adt/list.h>
#include <libadt/list.h>
#include <fibril.h>
#include <thread.h>
#include <tls.h>
49,8 → 49,7
#define FIBRIL_INITIAL_STACK_PAGES_NO 1
#endif
 
/**
* This futex serializes access to ready_list, serialized_list and manager_list.
/** This futex serializes access to ready_list, serialized_list and manage_list.
*/
static atomic_t fibril_futex = FUTEX_INITIALIZER;
 
60,12 → 59,12
 
static void fibril_main(void);
 
/** Number of threads that are executing a manager fibril. */
static int threads_in_manager;
/** Number of threads that are executing a manager fibril and are serialized. */
static int serialized_threads; /* Protected by async_futex */
/** Fibril-local count of serialization. If > 0, we must not preempt */
static fibril_local int serialization_count;
/** Number of fibrils that are in async_serialized mode */
static int serialized_fibrils; /* Protected by async_futex */
/** Thread-local count of serialization. If >0, we must not preempt */
static __thread int serialization_count;
/** Counter for fibrils residing in async_manager */
static int fibrils_in_manager;
 
/** Setup fibril information into TCB structure */
fibril_t *fibril_setup(void)
144,11 → 143,11
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
/*
* Do not preempt if there is not enough threads to run the
* ready fibrils which are not serialized.
* Do not preempt if there is not sufficient count of fibril
* managers.
*/
if (list_empty(&serialized_list) &&
threads_in_manager <= serialized_threads) {
fibrils_in_manager <= serialized_fibrils) {
goto ret_0;
}
}
195,7 → 194,7
list_append(&srcf->link, &ready_list);
else if (stype == FIBRIL_FROM_MANAGER) {
list_append(&srcf->link, &manager_list);
threads_in_manager--;
fibrils_in_manager--;
} else {
/*
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to
209,10 → 208,10
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
dstf = list_get_instance(manager_list.next, fibril_t, link);
if (serialization_count && stype == FIBRIL_TO_MANAGER) {
serialized_threads++;
serialized_fibrils++;
srcf->flags |= FIBRIL_SERIALIZED;
}
threads_in_manager++;
fibrils_in_manager++;
 
if (stype == FIBRIL_FROM_DEAD)
dstf->clean_after_me = srcf;
220,7 → 219,7
if (!list_empty(&serialized_list)) {
dstf = list_get_instance(serialized_list.next, fibril_t,
link);
serialized_threads--;
serialized_fibrils--;
} else {
dstf = list_get_instance(ready_list.next, fibril_t,
link);
270,7 → 269,7
 
/** Add a fibril to the ready list.
*
* @param fid Pointer to the fibril structure of the fibril to be
* @param fid Pinter to the fibril structure of the fibril to be
* added.
*/
void fibril_add_ready(fid_t fid)
288,8 → 287,7
 
/** Add a fibril to the manager list.
*
* @param fid Pointer to the fibril structure of the fibril to be
* added.
* @param fid Pinter to the fibril structure of the fibril to be added.
*/
void fibril_add_manager(fid_t fid)
{
316,8 → 314,7
 
/** Return fibril id of the currently running fibril.
*
* @return fibril ID of the currently running fibril.
*
* @return Fibril ID of the currently running pseudo thread.
*/
fid_t fibril_get_id(void)
{
324,14 → 321,13
return (fid_t) __tcb_get()->fibril_data;
}
 
/** Disable preemption
/** Disable preemption
*
* If the fibril wants to send several message in a row and does not want to be
* preempted, it should start async_serialize_start() in the beginning of
* communication and async_serialize_end() in the end. If it is a true
* multithreaded application, it should protect the communication channel by a
* futex as well.
*
* futex as well. Interrupt messages can still be preempted.
*/
void fibril_inc_sercount(void)
{
/branches/network/uspace/lib/libc/generic/libadt/hash_table.c
0,0 → 1,196
/*
* Copyright (c) 2008 Jakub Jermar
* 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
*/
 
/*
* This is an implementation of generic chained hash table.
*/
 
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <unistd.h>
#include <malloc.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
 
/** Create chained hash table.
*
* @param h Hash table structure. Will be initialized by this call.
* @param m Number of hash table buckets.
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
* @return True on success
*/
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
hash_table_operations_t *op)
{
hash_count_t i;
 
assert(h);
assert(op && op->hash && op->compare);
assert(max_keys > 0);
h->entry = malloc(m * sizeof(link_t));
if (!h->entry) {
printf("cannot allocate memory for hash table\n");
return false;
}
memset((void *) h->entry, 0, m * sizeof(link_t));
for (i = 0; i < m; i++)
list_initialize(&h->entry[i]);
h->entries = m;
h->max_keys = max_keys;
h->op = op;
return true;
}
 
/** Destroy a hash table instance.
*
* @param h Hash table to be destroyed.
*/
void hash_table_destroy(hash_table_t *h)
{
assert(h);
assert(h->entry);
free(h->entry);
}
 
/** Insert item into a hash table.
*
* @param h Hash table.
* @param key Array of all keys necessary to compute hash index.
* @param item Item to be inserted into the hash table.
*/
void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
{
hash_index_t chain;
 
assert(item);
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
list_append(item, &h->entry[chain]);
}
 
/** Search hash table for an item matching keys.
*
* @param h Hash table.
* @param key Array of all keys needed to compute hash index.
*
* @return Matching item on success, NULL if there is no such item.
*/
link_t *hash_table_find(hash_table_t *h, unsigned long key[])
{
link_t *cur;
hash_index_t chain;
 
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, h->max_keys, cur)) {
/*
* The entry is there.
*/
return cur;
}
}
return NULL;
}
 
/** Remove all matching items from hash table.
*
* For each removed item, h->remove_callback() is called.
*
* @param h Hash table.
* @param key Array of keys that will be compared against items of
* the hash table.
* @param keys Number of keys in the 'key' array.
*/
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
{
hash_index_t chain;
link_t *cur;
 
assert(h && h->op && h->op->hash && h->op->compare &&
h->op->remove_callback);
assert(keys <= h->max_keys);
if (keys == h->max_keys) {
 
/*
* All keys are known, hash_table_find() can be used to find the
* entry.
*/
cur = hash_table_find(h, key);
if (cur) {
list_remove(cur);
h->op->remove_callback(cur);
}
return;
}
/*
* Fewer keys were passed.
* Any partially matching entries are to be removed.
*/
for (chain = 0; chain < h->entries; chain++) {
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, keys, cur)) {
link_t *hlp;
hlp = cur;
cur = cur->prev;
list_remove(hlp);
h->op->remove_callback(hlp);
continue;
}
}
}
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/libadt/list.c
0,0 → 1,89
/*
* Copyright (c) 2004 Jakub Jermar
* 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 <libadt/list.h>
 
 
/** Check for membership
*
* Check whether link is contained in the list head.
* The membership is defined as pointer equivalence.
*
* @param link Item to look for.
* @param head List to look in.
*
* @return true if link is contained in head, false otherwise.
*
*/
int list_member(const link_t *link, const link_t *head)
{
int found = false;
link_t *hlp = head->next;
while (hlp != head) {
if (hlp == link) {
found = true;
break;
}
hlp = hlp->next;
}
return found;
}
 
 
/** Concatenate two lists
*
* Concatenate lists head1 and head2, producing a single
* list head1 containing items from both (in head1, head2
* order) and empty list head2.
*
* @param head1 First list and concatenated output
* @param head2 Second list and empty output.
*
*/
void list_concat(link_t *head1, link_t *head2)
{
if (list_empty(head2))
return;
 
head2->next->prev = head1->prev;
head2->prev->next = head1;
head1->prev->next = head2->next;
head1->prev = head2->prev;
list_initialize(head2);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/ia64/include/types.h
49,6 → 49,8
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/ia64/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcia64
* @{
*/
/** @file
*/
 
#ifndef LIBC_ia64_BYTEORDER_H_
#define LIBC_ia64_BYTEORDER_H_
 
/* IA-64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/ia64/Makefile.inc
31,6 → 31,9
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
arch/$(UARCH)/src/fibril.S \
37,10 → 40,5
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/ddi.c
 
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
 
ENDIANESS = LE
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64-elf64
/branches/network/uspace/lib/libc/arch/sparc64/include/types.h
49,6 → 49,8
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/sparc64/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcsparc64
* @{
*/
/** @file
*/
 
#ifndef LIBC_sparc64_BYTEORDER_H_
#define LIBC_sparc64_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/sparc64/Makefile.inc
38,7 → 38,5
CFLAGS += -mcpu=ultrasparc -m64
LFLAGS += -no-check-sections -N
 
ENDIANESS = BE
 
BFD_NAME = elf64-sparc
BFD_ARCH = sparc
/branches/network/uspace/lib/libc/arch/arm32/include/types.h
50,6 → 50,8
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/arm32/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcarm32
* @{
*/
/** @file
* @brief Endianness definitions.
*/
 
#ifndef LIBC_arm32_BYTEORDER_H_
#define LIBC_arm32_BYTEORDER_H_
 
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/arm32/include/tls.h
40,7 → 40,7
 
#define CONFIG_TLS_VARIANT_1
 
/** Offsets for accessing thread-local variables are shifted 8 bytes higher. */
/** Offsets for accessing __thread variables are shifted 8 bytes higher. */
#define ARM_TP_OFFSET (-8)
 
/** TCB (Thread Control Block) struct.
/branches/network/uspace/lib/libc/arch/arm32/include/fibril.h
38,7 → 38,7
 
#include <sys/types.h>
#include <align.h>
#include <thread.h>
#include "thread.h"
 
/** Size of a stack item */
#define STACK_ITEM_SIZE 4
/branches/network/uspace/lib/libc/arch/arm32/Makefile.inc
32,6 → 32,9
 
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
38,10 → 41,5
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/eabi.S
 
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
 
ENDIANESS = LE
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
/branches/network/uspace/lib/libc/arch/ppc32/include/types.h
49,6 → 49,8
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/ppc32/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcppc32
* @{
*/
/** @file
*/
 
#ifndef LIBC_ppc32_BYTEORDER_H_
#define LIBC_ppc32_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/ppc32/Makefile.inc
40,7 → 40,5
AFLAGS += -a32
LFLAGS += -N
 
ENDIANESS = BE
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
/branches/network/uspace/lib/libc/arch/amd64/include/types.h
49,6 → 49,8
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/amd64/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcamd64
* @{
*/
/** @file
*/
 
#ifndef LIBC_amd64_BYTEORDER_H_
#define LIBC_amd64_BYTEORDER_H_
 
/* AMD64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/amd64/Makefile.inc
38,7 → 38,5
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf64-x86-64
BFD_ARCH = i386:x86-64
/branches/network/uspace/lib/libc/arch/mips32/include/types.h
50,6 → 50,8
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/mips32/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcmips32
* @{
*/
/** @file
*/
 
#ifndef LIBC_mips32_BYTEORDER_H_
#define LIBC_mips32_BYTEORDER_H_
 
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/mips32/Makefile.inc
31,14 → 31,11
 
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mips3
 
ENDIANESS = LE
 
BFD_ARCH = mips
BFD_NAME = elf32-tradlittlemips
/branches/network/uspace/lib/libc/arch/ia32/include/types.h
49,6 → 49,8
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/network/uspace/lib/libc/arch/ia32/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcia32
* @{
*/
/** @file
*/
 
#ifndef LIBC_ia32_BYTEORDER_H_
#define LIBC_ia32_BYTEORDER_H_
 
/* IA-32 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/ia32/Makefile.inc
39,7 → 39,5
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf32-i386
BFD_ARCH = i386
/branches/network/uspace/lib/libc/arch/mips32eb/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 Jakub Jermar
* 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 libcmips32
* @{
*/
/** @file
*/
 
#ifndef LIBC_mips32eb_BYTEORDER_H_
#define LIBC_mips32eb_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/network/uspace/lib/libc/arch/mips32eb/Makefile.inc
31,15 → 31,13
 
TARGET = mips-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mips3
LFLAGS += -N
 
ENDIANESS = BE
 
BFD_ARCH = mips
BFD_NAME = elf32-tradbigmips
/branches/network/uspace/lib/libc/Makefile.toolchain
26,11 → 26,10
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
-finput-charset=UTF-8 -fno-builtin -Wall -Wextra -Wno-unused-parameter \
-Wmissing-prototypes -Werror-implicit-function-declaration -nostdlib \
-nostdinc -pipe -g -D__$(ENDIANESS)__
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \
-Wmissing-prototypes -O3 -nostdlib -nostdinc -imacros \
$(LIBC_PREFIX)/../../../config.h -I$(LIBC_PREFIX)/include -pipe -g
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
 
/branches/network/uspace/lib/libc/Makefile
32,7 → 32,6
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
 
 
## Setup toolchain
#
 
47,12 → 46,11
generic/ddi.c \
generic/as.c \
generic/cap.c \
generic/devmap.c \
generic/console.c \
generic/event.c \
generic/mem.c \
generic/string.c \
generic/fibril.c \
generic/fibril_sync.c \
generic/pcb.c \
generic/smc.c \
generic/thread.c \
62,12 → 60,15
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/klog.c \
generic/io/fprintf.c \
generic/io/stdio.c \
generic/io/stream.c \
generic/io/sprintf.c \
generic/io/snprintf.c \
generic/io/vprintf.c \
generic/io/vsprintf.c \
generic/io/vsnprintf.c \
generic/io/printf_core.c \
generic/io/console.c \
malloc/malloc.c \
generic/sysinfo.c \
generic/ipc.c \
74,11 → 75,12
generic/async.c \
generic/loader.c \
generic/getopt.c \
generic/adt/list.o \
generic/adt/hash_table.o \
generic/libadt/list.o \
generic/libadt/hash_table.o \
generic/time.c \
generic/err.c \
generic/stdlib.c \
generic/kbd.c \
generic/mman.c \
generic/udebug.c \
generic/vfs/vfs.c \
/branches/network/uspace/lib/libfs/libfs.c
1,5 → 1,5
/*
* Copyright (c) 2009 Jakub Jermar
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
42,7 → 42,6
#include <as.h>
#include <assert.h>
#include <dirent.h>
#include <mem.h>
 
/** Register file system server.
*
123,106 → 122,23
return IPC_GET_RETVAL(answer);
}
 
void fs_node_initialize(fs_node_t *fn)
{
memset(fn, 0, sizeof(fs_node_t));
}
 
void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request);
int res;
ipcarg_t rc;
 
ipc_call_t call;
ipc_callid_t callid;
 
/* accept the phone */
callid = async_get_call(&call);
int mountee_phone = (int)IPC_GET_ARG1(call);
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
mountee_phone < 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */
res = ipc_data_write_receive(&callid, NULL);
if (!res) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
if (!fn) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
if (fn->mp_data.mp_active) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, EBUSY);
ipc_answer_0(rid, EBUSY);
return;
}
 
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
if (rc != 0) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, rc);
ipc_answer_0(rid, rc);
return;
}
ipc_call_t answer;
aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle,
&answer);
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
async_wait_for(msg, &rc);
if (rc == EOK) {
fn->mp_data.mp_active = true;
fn->mp_data.fs_handle = mr_fs_handle;
fn->mp_data.dev_handle = mr_dev_handle;
fn->mp_data.phone = mountee_phone;
}
/*
* Do not release the FS node so that it stays in memory.
*/
ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
IPC_GET_ARG3(answer));
}
 
/** Lookup VFS triplet by name in the file system name space.
*
* The path passed in the PLB must be in the canonical file system path format
* as returned by the canonify() function.
*
* @param ops libfs operations structure with function pointers to
* 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 ops libfs operations structure with function pointers to
* 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.
*/
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
unsigned first = IPC_GET_ARG1(*request);
unsigned next = IPC_GET_ARG1(*request);
unsigned last = IPC_GET_ARG2(*request);
unsigned next = first;
dev_handle_t dev_handle = IPC_GET_ARG3(*request);
int lflag = IPC_GET_ARG4(*request);
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
232,18 → 148,10
if (last < next)
last += PLB_SIZE;
 
fs_node_t *par = NULL;
fs_node_t *cur = ops->root_get(dev_handle);
fs_node_t *tmp = NULL;
void *par = NULL;
void *cur = ops->root_get(dev_handle);
void *tmp = NULL;
 
if (cur->mp_data.mp_active) {
ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP,
next, last, cur->mp_data.dev_handle, lflag, index,
IPC_FF_ROUTE_FROM_ME);
ops->node_put(cur);
return;
}
 
if (ops->plb_get_char(next) == '/')
next++; /* eat slash */
266,21 → 174,6
 
/* match the component */
tmp = ops->match(cur, component);
if (tmp && tmp->mp_data.mp_active) {
if (next > last)
next = last = first;
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);
ops->node_put(cur);
ops->node_put(tmp);
if (par)
ops->node_put(par);
return;
}
 
/* handle miss: match amongst siblings */
if (!tmp) {
296,33 → 189,39
ipc_answer_0(rid, ENOTDIR);
goto out;
}
fs_node_t *fn;
void *nodep;
if (lflag & L_CREATE)
fn = ops->create(dev_handle, lflag);
nodep = ops->create(dev_handle, lflag);
else
fn = ops->node_get(dev_handle,
nodep = ops->node_get(dev_handle,
index);
if (fn) {
if (nodep) {
int rc;
 
rc = ops->link(cur, fn, component);
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE) {
(void)ops->destroy(fn);
(void)ops->destroy(
nodep);
}
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
ops->index_get(fn),
ops->size_get(fn),
ops->lnkcnt_get(fn));
ops->node_put(fn);
ops->index_get(nodep),
ops->size_get(nodep),
ops->lnkcnt_get(nodep));
ops->node_put(nodep);
}
} else {
ipc_answer_0(rid, ENOSPC);
}
goto out;
} else if (lflag & L_PARENT) {
/* return parent */
ipc_answer_5(rid, EOK, fs_handle, dev_handle,
ops->index_get(cur), ops->size_get(cur),
ops->lnkcnt_get(cur));
}
ipc_answer_0(rid, ENOENT);
goto out;
364,26 → 263,26
assert(len);
component[len] = '\0';
fs_node_t *fn;
void *nodep;
if (lflag & L_CREATE)
fn = ops->create(dev_handle, lflag);
nodep = ops->create(dev_handle, lflag);
else
fn = ops->node_get(dev_handle, index);
if (fn) {
nodep = ops->node_get(dev_handle, index);
if (nodep) {
int rc;
 
rc = ops->link(cur, fn, component);
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE)
(void)ops->destroy(fn);
(void)ops->destroy(nodep);
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
ops->index_get(fn),
ops->size_get(fn),
ops->lnkcnt_get(fn));
ops->node_put(fn);
ops->index_get(nodep),
ops->size_get(nodep),
ops->lnkcnt_get(nodep));
ops->node_put(nodep);
}
} else {
ipc_answer_0(rid, ENOSPC);
395,9 → 294,18
}
 
/* handle hit */
if (lflag & L_PARENT) {
ops->node_put(cur);
cur = par;
par = NULL;
if (!cur) {
ipc_answer_0(rid, ENOENT);
goto out;
}
}
if (lflag & L_UNLINK) {
unsigned old_lnkcnt = ops->lnkcnt_get(cur);
int res = ops->unlink(par, cur, component);
int res = ops->unlink(par, cur);
ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
goto out;
428,32 → 336,5
ops->node_put(tmp);
}
 
/** 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.
*
*/
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t dev_handle = IPC_GET_ARG1(*request);
fs_index_t index = IPC_GET_ARG2(*request);
fs_node_t *node = ops->node_get(dev_handle, index);
if (node == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
ops->size_get(node), ops->lnkcnt_get(node));
ops->node_put(node);
}
 
/** @}
*/
/branches/network/uspace/lib/libfs/libfs.h
1,5 → 1,5
/*
* Copyright (c) 2009 Jakub Jermar
* Copyright (c) 2007 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,68 → 26,51
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libfs
/** @addtogroup libfs
* @{
*/
*/
/**
* @file
*/
 
#ifndef LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
 
#include <ipc/vfs.h>
#include "../../srv/vfs/vfs.h"
#include <stdint.h>
#include <ipc/ipc.h>
#include <async.h>
#include <devmap.h>
 
typedef struct {
bool mp_active;
int phone;
fs_handle_t fs_handle;
dev_handle_t dev_handle;
} mp_data_t;
 
typedef struct {
mp_data_t mp_data; /**< Mount point info. */
void *data; /**< Data of the file system implementation. */
} fs_node_t;
 
typedef struct {
fs_node_t * (* match)(fs_node_t *, const char *);
fs_node_t * (* node_get)(dev_handle_t, fs_index_t);
void (* node_put)(fs_node_t *);
fs_node_t * (* create)(dev_handle_t, int);
int (* destroy)(fs_node_t *);
int (* link)(fs_node_t *, fs_node_t *, const char *);
int (* unlink)(fs_node_t *, fs_node_t *, const char *);
fs_index_t (* index_get)(fs_node_t *);
size_t (* size_get)(fs_node_t *);
unsigned (* lnkcnt_get)(fs_node_t *);
bool (* has_children)(fs_node_t *);
fs_node_t *(* root_get)(dev_handle_t);
char (* plb_get_char)(unsigned pos);
bool (* is_directory)(fs_node_t *);
bool (* is_file)(fs_node_t *);
void * (* match)(void *, const char *);
void * (* node_get)(dev_handle_t, fs_index_t);
void (* node_put)(void *);
void * (* create)(dev_handle_t, int);
int (* destroy)(void *);
int (* link)(void *, void *, const char *);
int (* unlink)(void *, void *);
fs_index_t (* index_get)(void *);
size_t (* size_get)(void *);
unsigned (* lnkcnt_get)(void *);
bool (* has_children)(void *);
void *(* root_get)(dev_handle_t);
char (* plb_get_char)(unsigned pos);
bool (* is_directory)(void *);
bool (* is_file)(void *);
} libfs_ops_t;
 
typedef struct {
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
} fs_reg_t;
 
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t);
 
extern void fs_node_initialize(fs_node_t *);
 
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_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
ipc_call_t *);
 
#endif
 
/** @}
*/
 
/branches/network/uspace/lib/softfloat/Makefile
36,7 → 36,7
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -Iinclude -Iarch/$(UARCH)/include/
CFLAGS +=-Iinclude -Iarch/$(UARCH)/include/
 
## Sources
#
/branches/network/uspace/lib/softfloat/include/sftypes.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup softfloat
/** @addtogroup softfloat
* @{
*/
/** @file
41,40 → 41,40
typedef union {
float f;
uint32_t binary;
struct {
#if defined(__BE__)
uint32_t sign : 1;
uint32_t exp : 8;
uint32_t fraction : 23;
#elif defined(__LE__)
uint32_t fraction : 23;
uint32_t exp : 8;
uint32_t sign : 1;
#else
#error Unknown endianess
 
struct {
#if defined(ARCH_IS_BIG_ENDIAN)
uint32_t sign:1;
uint32_t exp:8;
uint32_t fraction:23;
#elif defined(ARCH_IS_LITTLE_ENDIAN)
uint32_t fraction:23;
uint32_t exp:8;
uint32_t sign:1;
#else
#error "Unknown endians."
#endif
} parts __attribute__ ((packed));
} float32;
 
} float32;
typedef union {
double d;
uint64_t binary;
struct {
#if defined(__BE__)
uint64_t sign : 1;
uint64_t exp : 11;
uint64_t fraction : 52;
#elif defined(__LE__)
uint64_t fraction : 52;
uint64_t exp : 11;
uint64_t sign : 1;
#else
#error Unknown endianess
struct {
#if defined(ARCH_IS_BIG_ENDIAN)
uint64_t sign:1;
uint64_t exp:11;
uint64_t fraction:52;
#elif defined(ARCH_IS_LITTLE_ENDIAN)
uint64_t fraction:52;
uint64_t exp:11;
uint64_t sign:1;
#else
#error "Unknown endians."
#endif
} parts __attribute__ ((packed));
} float64;
} parts __attribute__ ((packed));
} float64;
 
#define FLOAT32_MAX 0x7f800000
#define FLOAT32_MIN 0xff800000
109,5 → 109,7
 
#endif
 
/** @}
 
/** @}
*/
 
/branches/network/uspace/lib/libblock/libblock.c
37,8 → 37,8
 
#include "libblock.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <ipc/devmap.h>
#include <ipc/bd.h>
#include <ipc/services.h>
#include <errno.h>
#include <sys/mman.h>
46,13 → 46,12
#include <ipc/ipc.h>
#include <as.h>
#include <assert.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <mem.h>
#include <futex.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
 
/** Lock protecting the device connection list */
static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
static futex_t dcl_lock = FUTEX_INITIALIZER;
/** Device connection list head. */
static LIST_INITIALIZE(dcl_head);
 
60,17 → 59,16
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)
 
typedef struct {
fibril_mutex_t lock;
futex_t lock;
size_t block_size; /**< Block size. */
unsigned block_count; /**< Total number of blocks. */
hash_table_t block_hash;
link_t free_head;
enum cache_mode mode;
} cache_t;
 
typedef struct {
link_t link;
dev_handle_t dev_handle;
int dev_handle;
int dev_phone;
void *com_area;
size_t com_size;
80,22 → 78,19
cache_t *cache;
} devcon_t;
 
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size,
const void *src);
 
static devcon_t *devcon_search(dev_handle_t dev_handle)
{
link_t *cur;
 
fibril_mutex_lock(&dcl_lock);
futex_down(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *devcon = list_get_instance(cur, devcon_t, link);
if (devcon->dev_handle == dev_handle) {
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return devcon;
}
}
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return NULL;
}
 
119,25 → 114,25
devcon->bb_size = 0;
devcon->cache = NULL;
 
fibril_mutex_lock(&dcl_lock);
futex_down(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *d = list_get_instance(cur, devcon_t, link);
if (d->dev_handle == dev_handle) {
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
free(devcon);
return EEXIST;
}
}
list_append(&devcon->link, &dcl_head);
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return EOK;
}
 
static void devcon_remove(devcon_t *devcon)
{
fibril_mutex_lock(&dcl_lock);
futex_down(&dcl_lock);
list_remove(&devcon->link);
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
}
 
int block_init(dev_handle_t dev_handle, size_t com_size)
151,8 → 146,9
if (!com_area) {
return ENOMEM;
}
dev_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
if (dev_phone < 0) {
munmap(com_area, com_size);
return dev_phone;
254,8 → 250,7
.remove_callback = cache_remove_callback
};
 
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks,
enum cache_mode mode)
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks)
{
devcon_t *devcon = devcon_search(dev_handle);
cache_t *cache;
267,11 → 262,10
if (!cache)
return ENOMEM;
fibril_mutex_initialize(&cache->lock);
futex_initialize(&cache->lock, 1);
list_initialize(&cache->free_head);
cache->block_size = size;
cache->block_count = blocks;
cache->mode = mode;
 
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
&cache_ops)) {
290,10 → 284,10
 
static void block_initialize(block_t *b)
{
fibril_mutex_initialize(&b->lock);
futex_initialize(&b->lock, 1);
b->refcnt = 1;
b->dirty = false;
fibril_rwlock_initialize(&b->contents_lock);
rwlock_initialize(&b->contents_lock);
link_initialize(&b->free_link);
link_initialize(&b->hash_link);
}
322,7 → 316,7
assert(devcon->cache);
cache = devcon->cache;
fibril_mutex_lock(&cache->lock);
futex_down(&cache->lock);
l = hash_table_find(&cache->block_hash, &key);
if (l) {
/*
329,11 → 323,11
* We found the block in the cache.
*/
b = hash_table_get_instance(l, block_t, hash_link);
fibril_mutex_lock(&b->lock);
futex_down(&b->lock);
if (b->refcnt++ == 0)
list_remove(&b->free_link);
fibril_mutex_unlock(&b->lock);
fibril_mutex_unlock(&cache->lock);
futex_up(&b->lock);
futex_up(&cache->lock);
} else {
/*
* The block was not found in the cache.
384,8 → 378,8
* kill concurent operations on the cache while doing I/O on the
* block.
*/
fibril_mutex_lock(&b->lock);
fibril_mutex_unlock(&cache->lock);
futex_down(&b->lock);
futex_up(&cache->lock);
 
if (sync) {
/*
404,7 → 398,7
assert(rc == EOK);
}
 
fibril_mutex_unlock(&b->lock);
futex_up(&b->lock);
}
return b;
}
419,14 → 413,13
{
devcon_t *devcon = devcon_search(block->dev_handle);
cache_t *cache;
int rc;
 
assert(devcon);
assert(devcon->cache);
 
cache = devcon->cache;
fibril_mutex_lock(&cache->lock);
fibril_mutex_lock(&block->lock);
futex_down(&cache->lock);
futex_down(&block->lock);
if (!--block->refcnt) {
/*
* Last reference to the block was dropped, put the block on the
433,16 → 426,9
* 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);
assert(rc == EOK);
 
block->dirty = false;
}
}
fibril_mutex_unlock(&block->lock);
fibril_mutex_unlock(&cache->lock);
futex_up(&block->lock);
futex_up(&cache->lock);
}
 
/** Read data from a block device.
460,8 → 446,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)
block_read(int 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;
488,13 → 474,13
left -= rd;
}
if (*bufpos == (off_t) *buflen) {
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK,
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return (rc != EOK ? rc : (int) retval);
return (rc != EOK ? rc : retval);
*bufpos = 0;
*buflen = block_size;
504,31 → 490,5
return EOK;
}
 
/** Write block to block device.
*
* @param devcon Device connection.
* @param boff Block index.
* @param block_size Block size.
* @param src Buffer containing the data to write.
*
* @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)
{
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);
if ((rc != EOK) || (retval != EOK))
return (rc != EOK ? rc : (int) retval);
 
return EOK;
}
 
/** @}
*/
/branches/network/uspace/lib/libblock/libblock.h
39,9 → 39,10
 
#include <stdint.h>
#include "../../srv/vfs/vfs.h"
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
 
/*
* Flags that can be used with block_get().
62,14 → 63,14
typedef unsigned bn_t; /**< Block number type. */
 
typedef struct block {
/** Mutex protecting the reference count. */
fibril_mutex_t lock;
/** Futex protecting the reference count. */
futex_t lock;
/** Number of references to the block_t structure. */
unsigned refcnt;
/** If true, the block needs to be written back to the block device. */
bool dirty;
/** Readers / Writer lock protecting the contents of the block. */
fibril_rwlock_t contents_lock;
rwlock_t contents_lock;
/** Handle of the device where the block resides. */
dev_handle_t dev_handle;
/** Block offset on the block device. Counted in 'size'-byte blocks. */
84,14 → 85,6
void *data;
} block_t;
 
/** Caching mode */
enum cache_mode {
/** Write-Through */
CACHE_MODE_WT,
/** Write-Back */
CACHE_MODE_WB
};
 
extern int block_init(dev_handle_t, size_t);
extern void block_fini(dev_handle_t);
 
98,13 → 91,12
extern int block_bb_read(dev_handle_t, off_t, size_t);
extern void *block_bb_get(dev_handle_t);
 
extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode);
extern int block_cache_init(dev_handle_t, size_t, unsigned);
 
extern block_t *block_get(dev_handle_t, bn_t, int flags);
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_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
 
#endif
 
/branches/network/uspace/Makefile
37,18 → 37,14
lib/libblock \
lib/softint \
lib/softfloat \
srv/bd/ata_bd \
srv/bd/file_bd \
srv/bd/gxe_bd \
srv/bd/rd \
srv/ns \
srv/loader \
srv/fb \
srv/kbd \
srv/console \
srv/rd \
srv/fs/fat \
srv/fs/tmpfs \
srv/fs/devfs \
srv/vfs \
srv/devmap \
srv/net \
57,7 → 53,6
app/trace \
app/klog \
app/init \
app/getvc \
app/bdsh
 
ifeq ($(UARCH),amd64)
70,8 → 65,8
 
ifeq ($(UARCH),sparc64)
DIRS += \
srv/cir/fhc \
srv/cir/obio
srv/fhc \
srv/obio
endif
 
BUILDS := $(addsuffix .build,$(DIRS))