/branches/dd/uspace/lib/libfs/libfs.c |
---|
42,7 → 42,6 |
#include <as.h> |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
/** Register file system server. |
* |
215,7 → 214,6 |
* 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) |
428,32 → 426,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/dd/uspace/lib/libfs/libfs.h |
---|
36,11 → 36,10 |
#ifndef 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; |
84,10 → 83,9 |
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/dd/uspace/lib/libblock/libblock.c |
---|
47,9 → 47,8 |
#include <as.h> |
#include <assert.h> |
#include <futex.h> |
#include <adt/list.h> |
#include <adt/hash_table.h> |
#include <mem.h> |
#include <libadt/list.h> |
#include <libadt/hash_table.h> |
/** Lock protecting the device connection list */ |
static futex_t dcl_lock = FUTEX_INITIALIZER; |
/branches/dd/uspace/lib/libblock/libblock.h |
---|
41,8 → 41,8 |
#include "../../srv/vfs/vfs.h" |
#include <futex.h> |
#include <rwlock.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
/* |
* Flags that can be used with block_get(). |
/branches/dd/uspace/lib/libc/include/fibril_sync.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/adt/hash_table.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/adt/list.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/adt/fifo.h |
---|
File deleted |
/branches/dd/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/dd/uspace/lib/libc/include/string.h |
---|
54,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); |
78,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/dd/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); |
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/dd/uspace/lib/libc/include/async.h |
---|
43,17 → 43,13 |
typedef ipc_callid_t aid_t; |
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call); |
typedef void (*async_pending_t)(void); |
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); |
90,16 → 86,15 |
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); |
extern void async_set_pending(async_pending_t pend); |
/* Wrappers for simple communication */ |
#define async_msg_0(phone, method) \ |
258,6 → 253,8 |
fibril_dec_sercount(); |
} |
extern atomic_t async_futex; |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/libadt/list.h |
---|
0,0 → 1,201 |
/* |
* 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> |
/** Doubly linked list head and link type. */ |
typedef struct link { |
struct link *prev; /**< Pointer to the previous item in the list. */ |
struct link *next; /**< Pointer to the next item in the list. */ |
} link_t; |
/** 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) ? 1 : 0); |
} |
/** 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) |
{ |
part1->prev->next = part2; |
part2->prev->next = part1; |
link_t *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 *) (((void *)(link)) - ((void *) &(((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); |
extern unsigned int list_count(const link_t *link); |
#endif |
/** @} |
*/ |
/branches/dd/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/dd/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/dd/uspace/lib/libc/include/io/keycode.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/io/color.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/io/console.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/io/klog.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/io/style.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/io/stream.h |
---|
0,0 → 1,49 |
/* |
* 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 int klog_puts(const char *); |
extern void klog_update(void); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/io/printf_core.h |
---|
56,3 → 56,5 |
/** @} |
*/ |
/branches/dd/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/dd/uspace/lib/libc/include/ipc/vfs.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/ipc/devmap.h |
---|
35,7 → 35,7 |
#include <atomic.h> |
#include <ipc/ipc.h> |
#include <adt/list.h> |
#include <libadt/list.h> |
#define DEVMAP_NAME_MAXLEN 255 |
/branches/dd/uspace/lib/libc/include/ipc/console.h |
---|
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, |
/branches/dd/uspace/lib/libc/include/ipc/ipc.h |
---|
35,21 → 35,16 |
#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 *); |
75,7 → 70,6 |
#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)) |
#define ipc_call_sync_1_0(phoneid, method, arg1) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0) |
#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \ |
93,7 → 87,6 |
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) |
114,7 → 107,6 |
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) |
136,7 → 128,6 |
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) |
158,7 → 149,6 |
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) |
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 *); |
/* |
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); |
268,6 → 258,7 |
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t, int); |
/* |
* User-friendly wrappers for ipc_share_in_start(). |
*/ |
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/dd/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/dd/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/dd/uspace/lib/libc/include/stdio.h |
---|
37,28 → 37,22 |
#include <sys/types.h> |
#include <stdarg.h> |
#include <adt/list.h> |
#define EOF (-1) |
#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 |
typedef struct { |
/** Linked list pointer. */ |
link_t link; |
/** Underlying file descriptor. */ |
int fd; |
67,64 → 61,54 |
/** End-of-file indicator. */ |
int eof; |
/** Klog indicator */ |
int klog; |
/** Phone to the file provider */ |
int phone; |
} 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 *); |
/* Misc file functions */ |
extern int rename(const char *, const char *); |
extern int fgetc(FILE *); |
extern int fputc(int, FILE *); |
extern int fputs(const char *, FILE *); |
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/dd/uspace/lib/libc/include/unistd.h |
---|
52,17 → 52,13 |
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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/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 { |
50,7 → 49,6 |
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_load_program(loader_t *); |
extern int loader_run(loader_t *); |
extern void loader_abort(loader_t *); |
/branches/dd/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,7 → 45,6 |
* 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. */ |
57,15 → 55,9 |
/** 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/dd/uspace/lib/libc/include/macros.h |
---|
44,13 → 44,6 |
#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/dd/uspace/lib/libc/include/errno.h |
---|
41,7 → 41,6 |
#include <kernel/errno.h> |
#define EMFILE (-17) |
#define ENAMETOOLONG (-256) |
#define EISDIR (-257) |
#define ENOTDIR (-258) |
/branches/dd/uspace/lib/libc/include/dirent.h |
---|
46,6 → 46,7 |
struct dirent res; |
} DIR; |
extern DIR *opendir(const char *); |
extern struct dirent *readdir(DIR *); |
extern void rewinddir(DIR *); |
/branches/dd/uspace/lib/libc/include/fibril.h |
---|
36,7 → 36,7 |
#define LIBC_FIBRIL_H_ |
#include <libarch/fibril.h> |
#include <adt/list.h> |
#include <libadt/list.h> |
#include <libarch/tls.h> |
#ifndef context_set |
47,7 → 47,6 |
#endif /* context_set */ |
#define FIBRIL_SERIALIZED 1 |
#define FIBRIL_WRITER 2 |
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/dd/uspace/lib/libc/generic/adt/hash_table.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/generic/adt/list.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/generic/fibril_sync.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/generic/ddi.c |
---|
127,7 → 127,7 |
} |
#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); |
/branches/dd/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/dd/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/dd/uspace/lib/libc/generic/string.c |
---|
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/dd/uspace/lib/libc/generic/libc.c |
---|
31,25 → 31,24 |
* @{ |
* @} |
*/ |
/** @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; |
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/dd/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); |
/branches/dd/uspace/lib/libc/generic/devmap.c |
---|
99,8 → 99,6 |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
108,7 → 106,6 |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return -1; |
} |
118,8 → 115,6 |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
async_serialize_end(); |
return retval; |
} |
136,8 → 131,6 |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0, |
&answer); |
146,14 → 139,11 |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return retval; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
173,8 → 163,6 |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
183,14 → 171,11 |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return retval; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
226,7 → 211,7 |
return 0; |
ipcarg_t count; |
int retval = async_req_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count); |
int retval = ipc_call_sync_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count); |
if (retval != EOK) |
return 0; |
240,8 → 225,6 |
if (phone < 0) |
return 0; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer); |
249,14 → 232,11 |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return 0; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) |
return 0; |
/branches/dd/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,11 → 174,10 |
} 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); |
static void default_pending(void); |
/** |
* Pointer to a fibril function that will be used to handle connections. |
191,15 → 190,11 |
*/ |
static async_client_conn_t interrupt_received = default_interrupt_received; |
/** |
* Pointer to a fibril function that will be used to handle pending |
* operations. |
*/ |
static async_pending_t pending = default_pending; |
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. |
381,42 → 376,6 |
return true; |
} |
/** Pending fibril. |
* |
* After each call the pending operations are executed in a separate |
* fibril. The function pending() is c. |
* |
* @param arg Unused. |
* |
* @return Always zero. |
* |
*/ |
static int pending_fibril(void *arg) |
{ |
pending(); |
return 0; |
} |
/** Process pending actions. |
* |
* A new fibril is created which would process the pending operations. |
* |
* @return False if an error occured. |
* True if the execution was passed to the pending fibril. |
* |
*/ |
static bool process_pending(void) |
{ |
futex_down(&async_futex); |
fid_t fid = fibril_create(pending_fibril, NULL); |
fibril_add_ready(fid); |
futex_up(&async_futex); |
return true; |
} |
/** Return new incoming message for the current (fibril-local) connection. |
* |
* @param call Storage where the incoming call data will be stored. |
513,15 → 472,6 |
{ |
} |
/** Default fibril function that gets called to handle pending operations. |
* |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
*/ |
static void default_pending(void) |
{ |
} |
/** Wrapper for client connection fibril. |
* |
* When a new connection arrives, a fibril with this implementing function is |
550,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); |
614,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); |
639,7 → 588,7 |
/* Unrouted call - do some default behaviour */ |
if ((callid & IPC_CALLID_NOTIFICATION)) { |
process_notification(callid, call); |
goto out; |
return; |
} |
switch (IPC_GET_METHOD(*call)) { |
648,19 → 597,15 |
/* 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: |
process_pending(); |
} |
/** Fire all timeouts that expired. */ |
718,8 → 663,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); |
736,8 → 681,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(); |
814,13 → 759,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(); |
1049,16 → 994,6 |
interrupt_received = intr; |
} |
/** Setter for pending function pointer. |
* |
* @param pend Function that will implement a new pending |
* operations fibril. |
*/ |
void async_set_pending(async_pending_t pend) |
{ |
pending = pend; |
} |
/** Pseudo-synchronous message sending - fast version. |
* |
* Send message asynchronously and return only after the reply arrives. |
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c |
---|
49,13 → 49,12 |
#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; |
214,7 → 213,6 |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
223,27 → 221,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 → 291,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; |
/branches/dd/uspace/lib/libc/generic/libadt/list.c |
---|
0,0 → 1,112 |
/* |
* 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 = 0; |
link_t *hlp = head->next; |
while (hlp != head) { |
if (hlp == link) { |
found = 1; |
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); |
} |
/** Count list items |
* |
* Return the number of items in the list. |
* |
* @param link List to count. |
* |
* @return Number of items in the list. |
* |
*/ |
unsigned int list_count(const link_t *link) |
{ |
unsigned int count = 0; |
link_t *hlp = link->next; |
while (hlp != link) { |
count++; |
hlp = hlp->next; |
} |
return count; |
} |
/** @} |
*/ |
/branches/dd/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/dd/uspace/lib/libc/generic/io/klog.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/generic/io/console.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/generic/io/io.c |
---|
32,419 → 32,96 |
/** @file |
*/ |
#include <libc.h> |
#include <unistd.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <fcntl.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 FILE stdin_null = { |
.fd = -1, |
.error = true, |
.eof = true, |
.klog = false, |
.phone = -1 |
}; |
const static char nl = '\n'; |
static FILE stdout_klog = { |
.fd = -1, |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1 |
}; |
static FILE stderr_klog = { |
.fd = -1, |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1 |
}; |
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); |
} |
} |
for (count = 0; str[count] != 0; count++); |
void stdio_done(void) |
{ |
link_t *link = files.next; |
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; |
return EOF; |
} |
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; |
} |
/** 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; |
list_append(&stream->link, &files); |
return stream; |
} |
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; |
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; |
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; |
size_t count; |
while ((left > 0) && (!stream->error) && (!stream->eof)) { |
ssize_t rd = read(stream->fd, buf + done, left); |
if (str == NULL) |
return putnchars("(NULL)", 6); |
if (rd < 0) |
stream->error = true; |
else if (rd == 0) |
stream->eof = true; |
else { |
left -= rd; |
done += rd; |
} |
} |
for (count = 0; str[count] != 0; count++); |
if (console_write((void *) str, count) == count) |
return 0; |
return (done / size); |
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 putchar(int c) |
{ |
size_t left = size * nmemb; |
size_t done = 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); |
} |
int fputc(wchar_t c, FILE *stream) |
{ |
char buf[STR_BOUNDS(1)]; |
size_t sz = 0; |
size_t offs; |
if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) { |
size_t wr = fwrite(buf, sz, 1, stream); |
if (wr < sz) |
offs = 0; |
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK) |
return EOF; |
return (int) c; |
} |
if (console_write((void *) buf, offs) == offs) |
return c; |
return EOF; |
} |
int putchar(wchar_t c) |
int getchar(void) |
{ |
return fputc(c, stdout); |
} |
unsigned char c; |
int fputs(const char *str, FILE *stream) |
{ |
return fwrite(str, str_size(str), 1, stream); |
} |
console_flush(); |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
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) |
int fflush(FILE *f) |
{ |
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) |
{ |
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/dd/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++; |
} |
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream) |
return chars; |
} |
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/dd/uspace/lib/libc/generic/io/stream.c |
---|
0,0 → 1,86 |
/* |
* 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; |
} |
/** Write a string to klog. */ |
int klog_puts(const char *str) |
{ |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) str, str_size(str)); |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
} |
/** @} |
*/ |
/branches/dd/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/dd/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/dd/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) { |
310,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) { |
432,7 → 432,7 |
} |
width -= precision + size - number_size; |
size_t counter = 0; |
count_t counter = 0; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
while (width-- > 0) { |
595,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/dd/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/dd/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/dd/uspace/lib/libc/generic/io/asprintf.c |
---|
36,49 → 36,39 |
#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. |
* @fmt Format strin. |
* |
* @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, |
asprintf_prewrite, |
NULL |
}; |
int ret; |
va_list args; |
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); |
vsprintf(*strp, fmt, args); |
va_end(args); |
} |
/branches/dd/uspace/lib/libc/generic/io/printf.c |
---|
34,40 → 34,20 |
#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); |
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); |
ret = vprintf(fmt, args); |
va_end(args); |
/branches/dd/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/dd/uspace/lib/libc/generic/io/snprintf.c |
---|
37,21 → 37,19 |
#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); |
ret = vsnprintf(str, size, fmt, args); |
int ret = vsnprintf(str, size, fmt, args); |
va_end(args); |
return ret; |
/branches/dd/uspace/lib/libc/generic/task.c |
---|
39,13 → 39,11 |
#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; |
55,9 → 53,7 |
* |
* @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) |
{ |
71,20 → 67,21 |
* |
* @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; |
94,38 → 91,10 |
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) |
137,11 → 106,12 |
goto error; |
/* Success */ |
free(ldr); |
return task_id; |
/* Error exit */ |
error: |
/* Error exit */ |
loader_abort(ldr); |
free(ldr); |
148,10 → 118,5 |
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/dd/uspace/lib/libc/generic/loader.c |
---|
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). |
* |
* de-allocated using free() after use). |
*/ |
int loader_spawn(const char *name) |
{ |
62,11 → 59,14 |
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; |
80,22 → 80,23 |
* |
* @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; |
} |
108,21 → 109,25 |
* |
* @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; |
130,11 → 135,11 |
free(pa); |
ipcarg_t retval; |
async_wait_for(req, &retval); |
return (int) retval; |
} |
/** Set command-line arguments for the program. |
* |
* Sets the vector of command-line arguments to be passed to the loaded |
143,41 → 148,48 |
* |
* @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; |
184,8 → 196,7 |
} |
async_wait_for(req, &rc); |
if (rc != EOK) |
return rc; |
if (rc != EOK) return rc; |
/* Free temporary buffer */ |
free(arg_buf); |
193,76 → 204,25 |
return EOK; |
} |
/** Set preset files for the program. |
/** Instruct loader to load 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. |
* If this function succeeds, the program has been successfully loaded |
* and is ready to be executed. |
* |
* @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[]) |
int loader_load_program(loader_t *ldr) |
{ |
/* |
* 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++; |
} |
int rc; |
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); |
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD); |
if (rc != EOK) |
return rc; |
/* Free temporary buffer */ |
free(files_buf); |
return EOK; |
} |
/** Instruct loader to load the program. |
* |
* 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. |
* |
*/ |
int loader_load_program(loader_t *ldr) |
{ |
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD); |
} |
/** Instruct loader to execute the program. |
* |
* Note that this function blocks until the loader actually replies |
273,13 → 233,13 |
* on the loader structure. It should be de-allocated using free(). |
* |
* @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; |
295,9 → 255,7 |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
void loader_abort(loader_t *ldr) |
{ |
/branches/dd/uspace/lib/libc/generic/as.c |
---|
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/dd/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) |
{ |
330,8 → 327,7 |
* 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/dd/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/dd/uspace/lib/libc/Makefile |
---|
46,12 → 46,12 |
generic/ddi.c \ |
generic/as.c \ |
generic/cap.c \ |
generic/console.c \ |
generic/devmap.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 \ |
61,12 → 61,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 \ |
73,11 → 76,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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/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/dd/uspace/lib/libc/Makefile.toolchain |
---|
26,10 → 26,10 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \ |
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration \ |
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \ |
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \ |
-Werror-implicit-function-declaration -nostdlib -nostdinc -pipe -g |
-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/dd/uspace/srv/cir/obio/Makefile |
---|
File deleted |
/branches/dd/uspace/srv/cir/obio/obio.c |
---|
File deleted |
Property changes: |
Deleted: svn:mergeinfo |
/branches/dd/uspace/srv/cir/obio |
---|
Property changes: |
Deleted: svn:mergeinfo |
/branches/dd/uspace/srv/cir/fhc/Makefile |
---|
File deleted |
/branches/dd/uspace/srv/cir/fhc/fhc.c |
---|
File deleted |
/branches/dd/uspace/srv/console/gcons.h |
---|
32,24 → 32,19 |
/** @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/dd/uspace/srv/console/screenbuffer.h |
---|
37,7 → 37,6 |
#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 */ |
73,7 → 72,7 |
/** One field on screen. It contain one character and its attributes. */ |
typedef struct { |
wchar_t character; /**< Character itself */ |
attrs_t attrs; /**< Character attributes */ |
attrs_t attrs; /**< Character`s attributes */ |
} keyfield_t; |
/** Structure for buffering state of one virtual console. |
81,17 → 80,17 |
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 */ |
unsigned int size_x; /**< Number of columns */ |
unsigned int size_y; /**< Number of rows */ |
/** Coordinates of last printed character for determining cursor position */ |
size_t position_x; |
size_t position_y; |
unsigned int position_x; |
unsigned int position_y; |
attrs_t attrs; /**< Current attributes. */ |
size_t top_line; /**< Points to buffer[][] line that will |
unsigned int 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 */ |
unsigned char is_cursor_visible; /**< Cursor state - default is visible */ |
} screenbuffer_t; |
/** Returns keyfield for position on screen |
106,7 → 105,7 |
* @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; |
} |
139,17 → 138,17 |
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/dd/uspace/srv/console/console.c |
---|
36,30 → 36,37 |
#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 "console.h" |
#include "gcons.h" |
#include "screenbuffer.h" |
#define NAME "console" |
#define MAX_DEVICE_NAME 32 |
#define MAX_KEYREQUESTS_BUFFERED 32 |
/** Size of cwrite_buf. */ |
#define CWRITE_BUF_SIZE 256 |
/** Index of currently used virtual console. |
*/ |
int active_console = 0; |
int prev_console = 0; |
/** Phone to the keyboard driver. */ |
static int kbd_phone; |
66,26 → 73,28 |
/** Information about framebuffer */ |
struct { |
int phone; /**< Framebuffer phone */ |
ipcarg_t rows; /**< Framebuffer rows */ |
ipcarg_t cols; /**< Framebuffer columns */ |
ipcarg_t rows; /**< Framebuffer rows */ |
} 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 |
/** 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. */ |
} console_t; |
} connection_t; |
/** Array of data for virtual consoles */ |
static console_t consoles[CONSOLE_COUNT]; |
static connection_t connections[CONSOLE_COUNT]; |
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; |
92,69 → 101,34 |
/** 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 cnt; /**< Width of the span. */ |
} fb_pending; |
/** Pending input structure. */ |
typedef struct { |
link_t link; |
console_t *cons; /**< Console waiting for input */ |
ipc_callid_t rid; /**< Call ID waiting for input */ |
ipc_callid_t callid; /**< Call ID waiting for IPC_DATA_READ */ |
/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */ |
static char cwrite_buf[CWRITE_BUF_SIZE]; |
size_t pos; /**< Position of the last stored data */ |
size_t size; /**< Size of ther buffer */ |
char *data; /**< Already stored data */ |
} pending_input_t; |
LIST_INITIALIZE(pending_input); |
/** Process pending input requests */ |
static void process_pending_input(void) |
/** Find unused virtual console. |
* |
*/ |
static int find_free_connection(void) |
{ |
async_serialize_start(); |
int i; |
link_t *cur; |
loop: |
for (cur = pending_input.next; cur != &pending_input; cur = cur->next) { |
pending_input_t *pr = list_get_instance(cur, pending_input_t, link); |
console_event_t ev; |
if (keybuffer_pop(&pr->cons->keybuffer, &ev)) { |
if (pr->data != NULL) { |
if (ev.type == KEY_PRESS) { |
pr->data[pr->pos] = ev.c; |
pr->pos++; |
for (i = 0; i < CONSOLE_COUNT; i++) { |
if (!connections[i].used) |
return i; |
} |
} else { |
ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c); |
list_remove(cur); |
free(pr); |
goto loop; |
return -1; |
} |
} |
if ((pr->data != NULL) && (pr->pos == pr->size)) { |
(void) ipc_data_read_finalize(pr->callid, pr->data, pr->size); |
ipc_answer_1(pr->rid, EOK, pr->size); |
free(pr->data); |
list_remove(cur); |
free(pr); |
goto loop; |
static void clrscr(void) |
{ |
async_msg_0(fb_info.phone, FB_CLEAR); |
} |
} |
async_serialize_end(); |
} |
static void curs_visibility(bool visible) |
{ |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); |
165,16 → 139,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); |
227,21 → 196,23 |
} |
/** 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; |
int j; |
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); |
x, y, w, h); |
} |
} |
248,8 → 219,11 |
/** Flush pending cells to FB. */ |
static void fb_pending_flush(void) |
{ |
screenbuffer_t *scr |
= &(connections[active_console].screenbuffer); |
if (fb_pending.cnt > 0) { |
fb_update_area(active_console, fb_pending.col, |
fb_update_area(&connections[active_console], fb_pending.col, |
fb_pending.row, fb_pending.cnt, 1); |
fb_pending.cnt = 0; |
} |
261,18 → 235,18 |
* 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 ((row != fb_pending.row) |
|| (col != fb_pending.col + fb_pending.cnt)) { |
fb_pending_flush(); |
} |
} |
if (fb_pending.cnt == 0) { |
fb_pending.row = row; |
fb_pending.col = col; |
fb_pending.row = row; |
} |
fb_pending.cnt++; |
279,67 → 253,82 |
} |
/** 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(); |
cons->scr.position_y++; |
cons->scr.position_x = 0; |
flush_cursor = true; |
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); |
if (console == active_console) |
cell_mark_changed(scr->position_y, scr->position_x); |
screenbuffer_putchar(&cons->scr, ch); |
cons->scr.position_x++; |
screenbuffer_putchar(scr, ch); |
scr->position_x++; |
} |
if (cons->scr.position_x >= cons->scr.size_x) |
cons->scr.position_y++; |
if (scr->position_x >= scr->size_x) { |
flush_cursor = true; |
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); |
} |
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; |
int j; |
int 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(); |
347,67 → 336,67 |
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(); |
} |
416,19 → 405,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_callid_t callid; |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
int retval; |
console_event_t ev; |
kbd_event_t ev; |
connection_t *conn; |
int newcon; |
/* Ignore parameters, the connection is alread opened */ |
while (true) { |
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; |
437,17 → 438,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; |
} |
keybuffer_push(&active_console->keybuffer, &ev); |
/* 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; |
} |
455,10 → 469,14 |
} |
} |
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); |
465,146 → 483,49 |
return; |
} |
char *buf = (char *) malloc(size); |
if (buf == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if (size > CWRITE_BUF_SIZE) |
size = CWRITE_BUF_SIZE; |
(void) ipc_data_write_finalize(callid, buf, size); |
(void) ipc_data_write_finalize(callid, cwrite_buf, size); |
async_serialize_start(); |
size_t off = 0; |
off = 0; |
while (off < size) { |
wchar_t ch = str_decode(buf, &off, size); |
write_char(cons, ch); |
ch = str_decode(cwrite_buf, &off, size); |
write_char(consnum, ch); |
} |
if (cons == active_console) |
curs_goto(cons->scr.position_x, cons->scr.position_y); |
async_serialize_end(); |
gcons_notify_char(cons->index); |
gcons_notify_char(consnum); |
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; |
} |
async_serialize_start(); |
size_t pos = 0; |
console_event_t ev; |
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 { |
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t)); |
if (!pr) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(buf); |
async_serialize_end(); |
return; |
} |
pr->cons = cons; |
pr->rid = rid; |
pr->callid = callid; |
pr->pos = pos; |
pr->size = size; |
pr->data = buf; |
list_append(&pr->link, &pending_input); |
} |
async_serialize_end(); |
} |
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) |
{ |
async_serialize_start(); |
console_event_t ev; |
if (keybuffer_pop(&cons->keybuffer, &ev)) { |
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c); |
} else { |
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t)); |
if (!pr) { |
ipc_answer_0(rid, ENOMEM); |
async_serialize_end(); |
return; |
} |
pr->cons = cons; |
pr->rid = rid; |
pr->callid = 0; |
pr->data = NULL; |
list_append(&pr->link, &pending_input); |
} |
async_serialize_end(); |
} |
/** 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); |
616,55 → 537,64 |
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: |
case CONSOLE_PUTCHAR: |
write_char(consnum, IPC_GET_ARG1(call)); |
gcons_notify_char(consnum); |
break; |
case CONSOLE_WRITE: |
async_serialize_end(); |
cons_read(cons, callid, &call); |
cons_write(consnum, callid, &call); |
async_serialize_start(); |
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) |
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: |
672,8 → 602,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: |
680,27 → 611,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(); |
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); |
} |
} |
709,26 → 659,28 |
change_console(prev_console); |
} |
static bool console_init(void) |
int main(int argc, char *argv[]) |
{ |
async_serialize_start(); |
printf(NAME ": HelenOS Console service\n"); |
ipcarg_t phonehash; |
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"); |
async_serialize_end(); |
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"); |
async_serialize_end(); |
return false; |
return -1; |
} |
async_set_pending(process_pending_input); |
async_new_connection(phonehash, 0, NULL, keyboard_events); |
/* Connect to framebuffer driver */ |
735,32 → 687,50 |
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0); |
if (fb_info.phone < 0) { |
printf(NAME ": Failed to connect to video service\n"); |
async_serialize_end(); |
return -1; |
} |
/* Register driver */ |
int rc = devmap_driver_register(NAME, client_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver (%d)\n", rc); |
async_serialize_end(); |
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.cnt = 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, |
770,45 → 740,14 |
} |
} |
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); |
async_serialize_end(); |
return false; |
} |
screenbuffer_clear(&consoles[i].scr); |
keybuffer_init(&consoles[i].keybuffer); |
consoles[i].index = i; |
consoles[i].refcount = 0; |
/* Register at NS */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
return -1; |
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); |
async_serialize_end(); |
return false; |
} |
} |
} |
/* Disable kernel output to the console */ |
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE); |
/* Initialize the screen */ |
gcons_redraw_console(); |
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
screen_clear(); |
curs_goto(0, 0); |
curs_visibility(active_console->scr.is_cursor_visible); |
/* Receive kernel notifications */ |
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) |
printf(NAME ": Error registering kconsole notifications\n"); |
815,18 → 754,8 |
async_set_interrupt_received(interrupt_received); |
async_serialize_end(); |
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/dd/uspace/srv/console/screenbuffer.c |
---|
33,7 → 33,7 |
*/ |
#include <screenbuffer.h> |
#include <io/style.h> |
#include <console/style.h> |
#include <malloc.h> |
#include <unistd.h> |
66,7 → 66,7 |
* @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) |
90,7 → 90,7 |
*/ |
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 = ' '; |
98,8 → 98,8 |
} |
scr->top_line = 0; |
scr->position_y = 0; |
scr->position_x = 0; |
scr->position_y = 0; |
} |
/** Clear one buffer line. |
108,13 → 108,13 |
* @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; |
} |
} |
126,9 → 126,9 |
*/ |
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]; |
} |
139,7 → 139,7 |
* @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; |
152,7 → 152,7 |
* @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; |
165,7 → 165,7 |
* @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; |
180,7 → 180,7 |
* @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; |
/branches/dd/uspace/srv/console/gcons.c |
---|
39,7 → 39,6 |
#include <sys/mman.h> |
#include <string.h> |
#include <align.h> |
#include <bool.h> |
#include "console.h" |
#include "gcons.h" |
55,9 → 54,8 |
#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]); |
char data[5]; |
int i; |
enum butstate state = console_state[consnum]; |
enum butstate state = console_state[index]; |
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,73 |
console_state[active_console] = CONS_DISCONNECTED; |
else |
console_state[active_console] = CONS_IDLE; |
redraw_state(active_console); |
} |
active_console = consnum; |
active_console = index; |
if (console_state[consnum] == CONS_DISCONNECTED) { |
console_state[consnum] = CONS_DISCONNECTED_SEL; |
redraw_state(consnum); |
} else |
console_state[consnum] = CONS_SELECTED; |
redraw_state(consnum); |
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); |
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(index); |
redraw_state(consnum); |
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); |
} |
240,23 → 227,24 |
} |
/** 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) |
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); |
284,9 → 272,9 |
/** 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; |
293,7 → 281,7 |
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; |
} |
303,7 → 291,7 |
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)) |
385,11 → 373,9 |
* |
* @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; |
478,9 → 464,13 |
/** 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; |
493,21 → 483,17 |
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); |
} |
515,28 → 501,27 |
/* Initialize icons */ |
ic_pixmaps[CONS_SELECTED] = |
make_pixmap(_binary_gfx_cons_selected_ppm_start, |
(size_t) &_binary_gfx_cons_selected_ppm_size); |
(int) &_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); |
(int) &_binary_gfx_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); |
(int) &_binary_gfx_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); |
(int) &_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); |
(int) &_binary_gfx_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/dd/uspace/srv/console/Makefile |
---|
46,7 → 46,7 |
GENERIC_SOURCES = \ |
console.c \ |
screenbuffer.c \ |
../kbd/generic/keybuffer.c \ |
../kbd/generic/key_buffer.c \ |
gcons.c |
IMAGES = \ |
/branches/dd/uspace/srv/bd/file_bd/file_bd.c |
---|
File deleted |
/branches/dd/uspace/srv/bd/file_bd/Makefile |
---|
File deleted |
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.c |
---|
File deleted |
/branches/dd/uspace/srv/bd/ata_bd/Makefile |
---|
File deleted |
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.h |
---|
File deleted |
/branches/dd/uspace/srv/bd/gxe_bd/gxe_bd.c |
---|
58,10 → 58,6 |
STATUS_FAILURE = 0 |
}; |
enum { |
MAX_DISKS = 2 |
}; |
typedef struct { |
uint32_t offset_lo; |
uint32_t pad0; |
76,12 → 72,17 |
uint32_t status; |
/* FIXME: Need to fix pio_enable() to support >= page_size areas. |
uint32_t pad4[3]; |
uint8_t pad5[0x3fc0]; |
uint32_t pad5[0x3fc0]; |
uint8_t buffer[512]; |
uint8_t buffer[512];*/ |
} gxe_bd_t; |
typedef struct { |
uint8_t buffer[512]; |
} gxe_buf_t; |
static const size_t block_size = 512; |
static size_t comm_size; |
88,19 → 89,17 |
static uintptr_t dev_physical = 0x13000000; |
static gxe_bd_t *dev; |
static gxe_buf_t *devbuf; |
static dev_handle_t dev_handle[MAX_DISKS]; |
static uint32_t disk_id = 0; |
static atomic_t dev_futex = FUTEX_INITIALIZER; |
static int gxe_bd_init(void); |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
void *buf); |
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size, |
void *buf); |
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size, |
const void *buf); |
static int gx_bd_rdwr(ipcarg_t method, off_t offset, off_t size, void *buf); |
static int gxe_bd_read_block(uint64_t offset, size_t size, void *buf); |
static int gxe_bd_write_block(uint64_t offset, size_t size, const void *buf); |
int main(int argc, char **argv) |
{ |
118,9 → 117,9 |
static int gxe_bd_init(void) |
{ |
dev_handle_t dev_handle; |
void *vaddr; |
int rc, i; |
char name[16]; |
int rc; |
rc = devmap_driver_register(NAME, gxe_bd_connection); |
if (rc < 0) { |
136,16 → 135,20 |
dev = vaddr; |
for (i = 0; i < MAX_DISKS; i++) { |
snprintf(name, 16, "disk%d", i); |
rc = devmap_device_register(name, &dev_handle[i]); |
rc = pio_enable((void *) dev_physical + 0x4000, sizeof(gxe_buf_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
devbuf = vaddr; |
rc = devmap_device_register("disk0", &dev_handle); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s.\n", |
name); |
printf(NAME ": Unable to register device.\n"); |
return rc; |
} |
} |
return EOK; |
} |
156,27 → 159,11 |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t method; |
dev_handle_t dh; |
int flags; |
int retval; |
off_t idx; |
off_t size; |
int disk_id, i; |
/* Get the device handle. */ |
dh = IPC_GET_ARG1(*icall); |
/* Determine which disk device is the client connecting to. */ |
disk_id = -1; |
for (i = 0; i < MAX_DISKS; i++) |
if (dev_handle[i] == dh) |
disk_id = i; |
if (disk_id < 0) { |
ipc_answer_0(iid, EINVAL); |
return; |
} |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
209,8 → 196,7 |
retval = EINVAL; |
break; |
} |
retval = gx_bd_rdwr(disk_id, method, idx * size, |
size, fs_va); |
retval = gx_bd_rdwr(method, idx * size, size, fs_va); |
break; |
default: |
retval = EINVAL; |
220,8 → 206,7 |
} |
} |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
void *buf) |
static int gx_bd_rdwr(ipcarg_t method, off_t offset, off_t size, void *buf) |
{ |
int rc; |
size_t now; |
230,9 → 215,9 |
now = size < block_size ? size : block_size; |
if (method == BD_READ_BLOCK) |
rc = gxe_bd_read_block(disk_id, offset, now, buf); |
rc = gxe_bd_read_block(offset, now, buf); |
else |
rc = gxe_bd_write_block(disk_id, offset, now, buf); |
rc = gxe_bd_write_block(offset, now, buf); |
if (rc != EOK) |
return rc; |
249,8 → 234,7 |
return EOK; |
} |
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size, |
void *buf) |
static int gxe_bd_read_block(uint64_t offset, size_t size, void *buf) |
{ |
uint32_t status; |
size_t i; |
268,7 → 252,8 |
} |
for (i = 0; i < size; i++) { |
((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]); |
((uint8_t *) buf)[i] = w = |
pio_read_8(&devbuf->buffer[i]); |
} |
futex_up(&dev_futex); |
275,14 → 260,14 |
return EOK; |
} |
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size, |
const void *buf) |
static int gxe_bd_write_block(uint64_t offset, size_t size, const void *buf) |
{ |
uint32_t status; |
size_t i; |
uint32_t w; |
for (i = 0; i < size; i++) { |
pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]); |
pio_write_8(&devbuf->buffer[i], ((const uint8_t *) buf)[i]); |
} |
futex_down(&dev_futex); |
/branches/dd/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> |
596,11 → 596,6 |
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); |
623,22 → 618,6 |
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/dd/uspace/srv/fs/tmpfs/tmpfs.h |
---|
38,7 → 38,7 |
#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__) |
86,11 → 86,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/dd/uspace/srv/fs/tmpfs/tmpfs.c |
---|
114,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/dd/uspace/srv/fs/fat/fat_ops.c |
---|
48,8 → 48,8 |
#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 <futex.h> |
#include <sys/mman.h> |
1169,11 → 1169,6 |
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); |
1190,22 → 1185,6 |
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/dd/uspace/srv/fs/fat/fat.h |
---|
206,11 → 206,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/dd/uspace/srv/fs/fat/fat_idx.c |
---|
39,8 → 39,8 |
#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 <futex.h> |
/branches/dd/uspace/srv/fs/fat/fat_fat.c |
---|
46,7 → 46,6 |
#include <align.h> |
#include <assert.h> |
#include <futex.h> |
#include <mem.h> |
/** |
* The fat_alloc_lock futex protects all copies of the File Allocation Table |
/branches/dd/uspace/srv/fs/fat/fat.c |
---|
107,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/dd/uspace/srv/fs/devfs/devfs.c |
---|
74,12 → 74,6 |
case VFS_LOOKUP: |
devfs_lookup(callid, &call); |
break; |
case VFS_OPEN_NODE: |
devfs_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
devfs_device(callid, &call); |
break; |
case VFS_READ: |
devfs_read(callid, &call); |
break; |
89,12 → 83,6 |
case VFS_TRUNCATE: |
devfs_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
devfs_close(callid, &call); |
break; |
case VFS_SYNC: |
devfs_sync(callid, &call); |
break; |
case VFS_DESTROY: |
devfs_destroy(callid, &call); |
break; |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.c |
---|
41,56 → 41,13 |
#include <malloc.h> |
#include <string.h> |
#include <libfs.h> |
#include <adt/hash_table.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE]) |
/** Opened devices structure */ |
typedef struct { |
dev_handle_t handle; |
int phone; |
size_t refcount; |
link_t link; |
} device_t; |
/** Hash table of opened devices */ |
static hash_table_t devices; |
#define DEVICES_KEYS 1 |
#define DEVICES_KEY_HANDLE 0 |
#define DEVICES_BUCKETS 256 |
/* Implementation of hash table interface for the nodes hash table. */ |
static hash_index_t devices_hash(unsigned long key[]) |
{ |
return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS; |
} |
static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
device_t *dev = hash_table_get_instance(item, device_t, link); |
return (dev->handle == (dev_handle_t) key[DEVICES_KEY_HANDLE]); |
} |
static void devices_remove_callback(link_t *item) |
{ |
free(hash_table_get_instance(item, device_t, link)); |
} |
static hash_table_operations_t devices_ops = { |
.hash = devices_hash, |
.compare = devices_compare, |
.remove_callback = devices_remove_callback |
}; |
bool devfs_init(void) |
{ |
if (!hash_table_create(&devices, DEVICES_BUCKETS, |
DEVICES_KEYS, &devices_ops)) |
return false; |
if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0) |
return false; |
146,7 → 103,8 |
return; |
} |
if ((lflag & L_LINK) || (lflag & L_UNLINK)) { |
/* This is a read-only filesystem */ |
if ((lflag & L_CREATE) || (lflag & L_LINK) || (lflag & L_UNLINK)) { |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
165,7 → 123,7 |
ipc_answer_0(rid, ENOENT); |
} else { |
if (lflag & L_FILE) { |
size_t len; |
count_t len; |
if (last >= first) |
len = last - first + 1; |
else |
177,7 → 135,7 |
return; |
} |
size_t i; |
count_t i; |
for (i = 0; i < len; i++) |
name[i] = PLB_GET_CHAR(first + i); |
190,40 → 148,8 |
return; |
} |
if (lflag & L_OPEN) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
free(name); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
free(name); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev->handle = handle; |
dev->phone = phone; |
dev->refcount = 1; |
hash_table_insert(&devices, key, &dev->link); |
} else { |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
} |
free(name); |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1); |
} else |
ipc_answer_0(rid, ENOENT); |
230,61 → 156,6 |
} |
} |
void devfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t handle = IPC_GET_ARG2(*request); |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev->handle = handle; |
dev->phone = phone; |
dev->refcount = 1; |
hash_table_insert(&devices, key, &dev->link); |
} else { |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
ipc_answer_3(rid, EOK, 0, 1, L_FILE); |
} |
void devfs_device(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_answer_1(rid, EOK, (ipcarg_t) index); |
} else |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
291,43 → 162,14 |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
/* |
* Receive the read request. |
*/ |
ipc_callid_t callid; |
if (!ipc_data_read_receive(&callid, NULL)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), |
IPC_GET_ARG3(*request), &answer); |
/* Forward the IPC_M_DATA_READ request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_1(rid, rc, bytes); |
} else { |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
335,15 → 177,19 |
return; |
} |
size_t count = devmap_device_get_count(); |
size_t bytes = 0; |
if (index != 0) { |
(void) ipc_data_read_finalize(callid, NULL, bytes); |
} else { |
count_t count = devmap_device_get_count(); |
dev_desc_t *desc = malloc(count * sizeof(dev_desc_t)); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_1(rid, ENOMEM, 0); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
size_t max = devmap_device_get_devices(count, desc); |
count_t max = devmap_device_get_devices(count, desc); |
if (pos < max) { |
ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1); |
354,10 → 200,11 |
} |
free(desc); |
bytes = 1; |
} |
ipc_answer_1(rid, EOK, 1); |
ipc_answer_1(rid, EOK, bytes); |
} |
} |
void devfs_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
364,47 → 211,21 |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
/* |
* Receive the write request. |
*/ |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, NULL)) { |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), |
IPC_GET_ARG3(*request), &answer); |
/* Forward the IPC_M_DATA_WRITE request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_1(rid, rc, bytes); |
} else { |
/* Read-only filesystem */ |
ipc_answer_0(rid, ENOTSUP); |
// TODO |
ipc_answer_0(callid, ENOENT); |
ipc_answer_2(rid, ENOENT, 0, 0); |
} |
} |
void devfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
411,66 → 232,6 |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount--; |
if (dev->refcount == 0) { |
ipc_hangup(dev->phone); |
hash_table_remove(&devices, key, DEVICES_KEYS); |
} |
ipc_answer_0(rid, EOK); |
} else |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer); |
/* Wait for reply from the driver */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_0(rid, rc); |
} else |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_destroy(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.h |
---|
41,13 → 41,9 |
extern void devfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void devfs_mount(ipc_callid_t, ipc_call_t *); |
extern void devfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void devfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void devfs_device(ipc_callid_t, ipc_call_t *); |
extern void devfs_sync(ipc_callid_t, ipc_call_t *); |
extern void devfs_read(ipc_callid_t, ipc_call_t *); |
extern void devfs_write(ipc_callid_t, ipc_call_t *); |
extern void devfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void devfs_close(ipc_callid_t, ipc_call_t *); |
extern void devfs_destroy(ipc_callid_t, ipc_call_t *); |
#endif |
/branches/dd/uspace/srv/vfs/vfs_ops.c |
---|
44,8 → 44,8 |
#include <string.h> |
#include <bool.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <rwlock.h> |
#include <libadt/list.h> |
#include <unistd.h> |
#include <ctype.h> |
#include <fcntl.h> |
66,7 → 66,6 |
dev_handle_t dev_handle; /**< Device handle */ |
} pending_req_t; |
FIBRIL_MUTEX_INITIALIZE(pending_lock); |
LIST_INITIALIZE(pending_req); |
/** |
73,7 → 72,7 |
* 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); |
vfs_pair_t rootfs = { |
.fs_handle = 0, |
96,13 → 95,13 |
ipc_call_t answer; |
/* Resolve the path to the mountpoint. */ |
fibril_rwlock_write_lock(&namespace_rwlock); |
rwlock_write_lock(&namespace_rwlock); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
if (str_cmp(mp, "/") == 0) { |
/* Trying to mount root FS over root FS */ |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, EBUSY); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
109,15 → 108,15 |
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); |
ipc_answer_0(rid, rc); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
mp_node = vfs_node_get(&mp_res); |
if (!mp_node) { |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
142,18 → 141,18 |
rc = ipc_data_write_start(phone, (void *)opts, |
str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
async_wait_for(msg, NULL); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
async_wait_for(msg, &rc); |
if (rc != EOK) { |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
175,8 → 174,8 |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} else { |
/* |
183,8 → 182,8 |
* We can't resolve this without the root filesystem |
* being mounted first. |
*/ |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOENT); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
} |
208,13 → 207,13 |
/* 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(phone); |
async_wait_for(msg, NULL); |
/* 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); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
221,17 → 220,17 |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
async_wait_for(msg, NULL); |
/* 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); |
rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
async_wait_for(msg, &rc); |
if (rc == EOK) { |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
255,7 → 254,7 |
} |
ipc_answer_0(rid, rc); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
rwlock_write_unlock(&namespace_rwlock); |
} |
/** Process pending mount requests */ |
264,7 → 263,6 |
link_t *cur; |
loop: |
fibril_mutex_lock(&pending_lock); |
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
pending_req_t *pr = list_get_instance(cur, pending_req_t, link); |
284,11 → 282,8 |
free(pr->opts); |
list_remove(cur); |
free(pr); |
fibril_mutex_unlock(&pending_lock); |
fibril_yield(); |
goto loop; |
} |
fibril_mutex_unlock(&pending_lock); |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
467,9 → 462,7 |
pr->rid = rid; |
pr->dev_handle = dev_handle; |
link_initialize(&pr->link); |
fibril_mutex_lock(&pending_lock); |
list_append(&pr->link, &pending_req); |
fibril_mutex_unlock(&pending_lock); |
return; |
} |
513,11 → 506,10 |
/* |
* 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; |
} |
528,12 → 520,12 |
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); |
540,7 → 532,6 |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
555,18 → 546,18 |
* 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; |
577,18 → 568,18 |
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; |
595,7 → 586,7 |
} |
node->size = 0; |
} |
fibril_rwlock_write_unlock(&node->contents_rwlock); |
rwlock_write_unlock(&node->contents_rwlock); |
} |
/* |
627,209 → 618,13 |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
void vfs_close(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) |
{ |
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); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
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); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
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); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
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) |
{ |
872,7 → 667,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 |
879,9 → 674,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) { |
/* |
889,7 → 684,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); |
915,26 → 710,25 |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
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 |
968,40 → 762,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); |
} |
1030,16 → 824,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); |
} |
1069,10 → 863,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); |
} |
1103,13 → 897,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; |
} |
1123,7 → 917,7 |
futex_down(&nodes_futex); |
node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, EOK); |
} |
1204,11 → 998,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); |
1216,7 → 1010,7 |
} |
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); |
1225,7 → 1019,7 |
/* 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); |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
1240,7 → 1034,7 |
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); |
free(parentc); /* not needed anymore */ |
if (rc != EOK) { |
fibril_rwlock_write_unlock(&namespace_rwlock); |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
1249,7 → 1043,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); |
1265,7 → 1059,7 |
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); |
1276,7 → 1070,7 |
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); |
1285,7 → 1079,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); |
1299,7 → 1093,7 |
/* 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); |
1311,7 → 1105,7 |
futex_down(&nodes_futex); |
old_node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
vfs_node_put(new_node); |
/branches/dd/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" |
/** |
59,7 → 57,7 |
* This resource being per-connection and, in the first place, per-fibril, we |
* 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) |
91,7 → 89,7 |
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; |
} |
/branches/dd/uspace/srv/vfs/vfs.c |
---|
43,7 → 43,7 |
#include <bool.h> |
#include <string.h> |
#include <as.h> |
#include <adt/list.h> |
#include <libadt/list.h> |
#include <atomic.h> |
#include "vfs.h" |
94,9 → 94,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; |
121,15 → 118,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; |
176,7 → 164,6 |
/* |
* Set a connectio handling function/fibril. |
*/ |
async_set_pending(vfs_process_pending_mount); |
async_set_client_connection(vfs_connection); |
/* |
/branches/dd/uspace/srv/vfs/vfs.h |
---|
34,13 → 34,12 |
#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__) |
47,7 → 46,52 |
#define dprintf(...) |
#define VFS_FIRST IPC_FIRST_USER_METHOD |
/* Basic types. */ |
typedef int16_t fs_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 { |
54,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; |
84,6 → 128,45 |
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 |
typedef enum vfs_node_type { |
VFS_NODE_UNKNOWN, |
VFS_NODE_FILE, |
122,7 → 205,7 |
/** |
* Holding this rwlock prevents modifications of the node's contents. |
*/ |
fibril_rwlock_t contents_rwlock; |
rwlock_t contents_rwlock; |
} vfs_node_t; |
/** |
131,7 → 214,7 |
*/ |
typedef struct { |
/** Serializes access to this open file. */ |
fibril_mutex_t lock; |
futex_t lock; |
vfs_node_t *node; |
151,6 → 234,10 |
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. */ |
165,7 → 252,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); |
172,9 → 259,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 *); |
197,10 → 283,6 |
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/dd/uspace/srv/vfs/vfs_register.c |
---|
45,14 → 45,14 |
#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_MUTEX_INITIALIZE(fs_head_lock); |
atomic_t fs_head_futex = FUTEX_INITIALIZER; |
link_t fs_head; |
atomic_t fs_handle_next = { |
159,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) { |
180,7 → 180,8 |
return; |
} |
fibril_mutex_lock(&fs_head_lock); |
futex_down(&fs_head_futex); |
fibril_inc_sercount(); |
/* |
* Check for duplicit registrations. |
190,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); |
212,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); |
230,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); |
244,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); |
268,10 → 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_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. |
291,18 → 302,28 |
* 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); |
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; |
} |
314,18 → 335,23 |
{ |
bool found = false; |
fibril_mutex_lock(&fs_head_lock); |
/* |
* 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; |
fibril_mutex_unlock(&fs_head_lock); |
fibril_mutex_unlock(&fs->phone_lock); |
futex_up(&fs_head_futex); |
futex_up(&fs->phone_futex); |
return; |
} |
} |
fibril_mutex_unlock(&fs_head_lock); |
futex_up(&fs_head_futex); |
/* |
* Not good to get here. |
336,8 → 362,8 |
/** 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. |
*/ |
346,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); |
356,7 → 382,7 |
} |
} |
if (lock) |
fibril_mutex_unlock(&fs_head_lock); |
futex_up(&fs_head_futex); |
return handle; |
} |
/branches/dd/uspace/srv/vfs/vfs_node.c |
---|
39,8 → 39,8 |
#include <stdlib.h> |
#include <string.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <rwlock.h> |
#include <libadt/hash_table.h> |
#include <assert.h> |
#include <async.h> |
#include <errno.h> |
177,7 → 177,7 |
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); |
/branches/dd/uspace/srv/vfs/vfs_lookup.c |
---|
43,7 → 43,7 |
#include <stdarg.h> |
#include <bool.h> |
#include <futex.h> |
#include <adt/list.h> |
#include <libadt/list.h> |
#include <vfs/canonify.h> |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
63,7 → 63,6 |
* of the whole VFS tree. |
* |
* @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, ...) |
177,7 → 176,7 |
memset(plb, 0, cnt2); |
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); |
vfs_release_phone(phone); |
ipcarg_t rc; |
async_wait_for(req, &rc); |
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/dd/uspace/srv/pci/pci.h |
---|
2,10 → 2,9 |
#define PCI_H |
//#include <arch/types.h> |
#include <adt/list.h> |
#include <libadt/list.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
struct pci_drv; |
struct pci_dev; |
/branches/dd/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/dd/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/dd/uspace/srv/kbd/include/keybuffer.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/include/kbd.h |
---|
37,7 → 37,7 |
#ifndef KBD_KBD_H_ |
#define KBD_KBD_H_ |
#include <keybuffer.h> |
#include <key_buffer.h> |
#include <ipc/ipc.h> |
#define KBD_EVENT 1024 |
62,3 → 62,4 |
/** |
* @} |
*/ |
/branches/dd/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/dd/uspace/srv/kbd/include/layout.h |
---|
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; |
54,3 → 54,4 |
/** |
* @} |
*/ |
/branches/dd/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/dd/uspace/srv/kbd/generic/keybuffer.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/generic/kbd.c |
---|
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(); |
/branches/dd/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/dd/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 = \ |
/branches/dd/uspace/srv/kbd/layout/cz.c |
---|
32,13 → 32,13 |
*/ |
#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, |
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,21 → 383,18 |
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/dd/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/dd/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/dd/uspace/srv/kbd/ctl/pc.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> |
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/dd/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/dd/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/dd/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/dd/uspace/srv/kbd/genarch/stroke.c |
---|
36,13 → 36,12 |
* 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; |
} |
/branches/dd/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/dd/uspace/srv/ns/clonable.c |
---|
File deleted |
/branches/dd/uspace/srv/ns/task.h |
---|
File deleted |
/branches/dd/uspace/srv/ns/ns.h |
---|
File deleted |
/branches/dd/uspace/srv/ns/clonable.h |
---|
File deleted |
/branches/dd/uspace/srv/ns/service.c |
---|
File deleted |
/branches/dd/uspace/srv/ns/task.c |
---|
File deleted |
/branches/dd/uspace/srv/ns/service.h |
---|
File deleted |
/branches/dd/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))) |
/branches/dd/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/dd/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 char **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,7 → 226,7 |
* @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; |
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; |
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,11 → 283,13 |
/* 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); |
} |
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/dd/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) { |
242,18 → 241,11 |
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: |
/branches/dd/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; |
1039,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) |
1565,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); |
1602,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; |
1621,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; |
1642,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/dd/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" |
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; |
144,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. |
241,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, |
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; |
default: return INVERTED_COLOR; |
} |
} |
316,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(); |
324,23 → 320,23 |
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: |
/branches/dd/uspace/srv/fb/ega.h |
---|
43,3 → 43,4 |
/** @} |
*/ |
/branches/dd/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/dd/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/dd/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; |
} |
/** |
* @} |
*/ |
/branches/dd/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> |
62,8 → 62,8 |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Fibril mutex for list of devices owned by this driver */ |
fibril_mutex_t devices_mutex; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
95,15 → 95,15 |
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_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; |
110,12 → 110,13 |
static dev_handle_t devmap_create_handle(void) |
{ |
/* 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); |
/* FIXME: overflow */ |
futex_down(&create_handle_futex); |
last_handle++; |
fibril_mutex_unlock(&create_handle_mutex); |
futex_up(&create_handle_futex); |
return last_handle; |
} |
130,7 → 131,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; |
} |
149,7 → 150,7 |
*/ |
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
futex_down(&devices_list_futex); |
link_t *item = (&devices_list)->next; |
devmap_device_t *device = NULL; |
162,13 → 163,13 |
} |
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; |
} |
248,7 → 249,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); |
257,13 → 258,13 |
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 |
271,7 → 272,7 |
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); |
286,7 → 287,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 |
296,7 → 297,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); |
313,7 → 314,7 |
if (driver == NULL) |
return EEXISTS; |
fibril_mutex_lock(&drivers_list_mutex); |
futex_down(&drivers_list_futex); |
if (driver->phone != 0) |
ipc_hangup(driver->phone); |
322,8 → 323,8 |
list_remove(&(driver->drivers)); |
/* Unregister all its devices */ |
fibril_mutex_lock(&devices_list_mutex); |
fibril_mutex_lock(&driver->devices_mutex); |
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, |
331,9 → 332,9 |
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) |
346,7 → 347,7 |
/** Process pending lookup requests */ |
static void process_pending_lookup(void) |
static void process_pending_lookup() |
{ |
link_t *cur; |
363,7 → 364,6 |
free(pr->name); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
419,12 → 419,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); |
440,14 → 440,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_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(); |
} |
/** |
598,14 → 600,14 |
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
futex_down(&devices_list_futex); |
ipc_answer_1(iid, EOK, list_count(&devices_list)); |
fibril_mutex_unlock(&devices_list_mutex); |
futex_up(&devices_list_futex); |
} |
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
futex_down(&devices_list_futex); |
ipc_callid_t callid; |
size_t size; |
621,7 → 623,7 |
return; |
} |
size_t count = size / sizeof(dev_desc_t); |
count_t count = size / sizeof(dev_desc_t); |
dev_desc_t *desc = (dev_desc_t *) malloc(size); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
629,7 → 631,7 |
return; |
} |
size_t pos = 0; |
count_t pos = 0; |
link_t *item = devices_list.next; |
while ((item != &devices_list) && (pos < count)) { |
650,7 → 652,7 |
free(desc); |
fibril_mutex_unlock(&devices_list_mutex); |
futex_up(&devices_list_futex); |
ipc_answer_1(iid, EOK, pos); |
} |
675,7 → 677,7 |
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
fibril_mutex_lock(&devices_list_mutex); |
futex_down(&devices_list_futex); |
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
684,7 → 686,7 |
/* Insert device into list of all devices */ |
list_append(&device->devices, &devices_list); |
fibril_mutex_unlock(&devices_list_mutex); |
futex_up(&devices_list_futex); |
return true; |
} |
711,6 → 713,7 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
cont = false; |
/* Exit thread */ |
continue; |
case DEVMAP_DRIVER_UNREGISTER: |
if (NULL == driver) |
763,6 → 766,7 |
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); |
818,9 → 822,7 |
return -1; |
} |
/* Set a handler of incomming connections and |
pending operations */ |
async_set_pending(process_pending_lookup); |
/* Set a handler of incomming connections */ |
async_set_client_connection(devmap_connection); |
/* Register device mapper at naming service */ |
/branches/dd/uspace/Makefile |
---|
37,8 → 37,6 |
lib/libblock \ |
lib/softint \ |
lib/softfloat \ |
srv/bd/ata_bd \ |
srv/bd/file_bd \ |
srv/bd/gxe_bd \ |
srv/bd/rd \ |
srv/ns \ |
56,7 → 54,6 |
app/trace \ |
app/klog \ |
app/init \ |
app/getvc \ |
app/bdsh |
ifeq ($(UARCH),amd64) |
73,10 → 70,10 |
ifeq ($(UARCH),sparc64) |
DIRS += \ |
srv/fhc \ |
srv/obio \ |
srv/pci \ |
app/lspci \ |
srv/cir/fhc \ |
srv/cir/obio |
app/lspci |
endif |
BUILDS := $(addsuffix .build,$(DIRS)) |
/branches/dd/uspace/app/getvc/version.c |
---|
File deleted |
/branches/dd/uspace/app/getvc/getvc.c |
---|
File deleted |
/branches/dd/uspace/app/getvc/version.h |
---|
File deleted |
/branches/dd/uspace/app/getvc/Makefile |
---|
File deleted |
/branches/dd/uspace/app/getvc/getvc.h |
---|
File deleted |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd.c |
---|
28,7 → 28,6 |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
/branches/dd/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/dd/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/dd/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/dd/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/dd/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,10 → 107,9 |
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) |
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,9 → 147,9 |
{ |
char line[INPUT_MAX]; |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
console_set_style(STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
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/dd/uspace/app/bdsh/exec.c |
---|
123,8 → 123,7 |
if (tid == 0) { |
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd); |
return 1; |
} |
task_wait(tid); |
} else { |
return 0; |
} |
} |
/branches/dd/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"); |
124,35 → 118,11 |
printf(NAME ": Error spawning %s\n", fname); |
} |
static void getvc(char *dev, char *app) |
{ |
char *argv[4]; |
char vc[MAX_DEVICE_NAME]; |
snprintf(vc, MAX_DEVICE_NAME, "/dev/%s", dev); |
printf(NAME ": Spawning getvc on %s\n", vc); |
dev_handle_t handle; |
devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING); |
if (handle >= 0) { |
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); |
} |
int main(int argc, char *argv[]) |
{ |
info_print(); |
if (!mount_root(STRING(RDFMT))) { |
if (!mount_fs(STRING(RDFMT))) { |
printf(NAME ": Exiting\n"); |
return -1; |
} |
170,14 → 140,12 |
spawn("/srv/fhc"); |
spawn("/srv/obio"); |
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"); |
usleep(1000000); |
spawn("/srv/pci"); |
/branches/dd/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))) |
/branches/dd/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/dd/uspace/app/init/init.h |
---|
38,9 → 38,8 |
#define NAME "init" |
#define MAX_DEVICE_NAME 32 |
#endif |
/** @} |
*/ |
/branches/dd/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/dd/uspace/app/tester/tester.c |
---|
130,7 → 130,6 |
list_tests(); |
printf("> "); |
fflush(stdout); |
c = getchar(); |
printf("%c\n", c); |
/branches/dd/uspace/app/tester/ipc/ping_pong.c |
---|
28,10 → 28,8 |
#include <stdio.h> |
#include <stdlib.h> |
#include <console.h> |
#include <sys/time.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <errno.h> |
#include "../tester.h" |
#define DURATION_SECS 10 |
39,16 → 37,19 |
char *test_ping_pong(bool quiet) |
{ |
printf("Pinging ns server for %d seconds...\n", DURATION_SECS); |
int i; |
int w, h; |
struct timeval start, now; |
long count; |
struct timeval start; |
printf("Pinging console server for %d seconds...\n", DURATION_SECS); |
if (gettimeofday(&start, NULL) != 0) |
return "Failed getting the time."; |
uint64_t count = 0; |
count = 0; |
while (true) { |
struct timeval now; |
if (gettimeofday(&now, NULL) != 0) |
return "Failed getting the time."; |
55,19 → 56,13 |
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) |
break; |
size_t i; |
for (i = 0; i < COUNT_GRANULARITY; i++) { |
int retval = async_req_0_0(PHONE_NS, NS_PING); |
if (retval != EOK) |
return "Failed to send ping message."; |
} |
for (i = 0; i < COUNT_GRANULARITY; i++) |
console_get_size(&w, &h); |
count += COUNT_GRANULARITY; |
} |
printf("Completed %lu round trips in %u seconds, %lu RT/s.\n", |
count, DURATION_SECS, count / DURATION_SECS); |
printf("Completed %ld round trips in %d seconds, %ld RT/s.\n", count, |
DURATION_SECS, count / DURATION_SECS); |
return NULL; |
} |
/branches/dd/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,21 → 50,21 |
int i, j; |
printf("Style test: "); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
console_set_style(STYLE_NORMAL); |
printf("normal "); |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
console_set_style(STYLE_EMPHASIS); |
printf("emphasized"); |
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++) { |
console_set_color(fphone(stdout), i, COLOR_WHITE, |
console_set_color(i, COLOR_WHITE, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
72,11 → 71,11 |
printf("Background color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
console_set_color(fphone(stdout), COLOR_WHITE, i, |
console_set_color(COLOR_WHITE, i, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
83,24 → 82,24 |
printf("Now let's test RGB colors:\n"); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 16); |
console_set_rgb_color(0xffffff, i << 16); |
putchar('X'); |
} |
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) { |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8); |
console_set_rgb_color(0xffffff, i << 8); |
putchar('X'); |
} |
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) { |
console_set_rgb_color(fphone(stdout), 0xffffff, i); |
console_set_rgb_color(0xffffff, i); |
putchar('X'); |
} |
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/dd/uspace/app/tetris/input.c |
---|
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,11 → 92,13 |
* 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. |
113,10 → 115,10 |
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) |
async_wait_for(getchar_inprog, &rc); |
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) { |
124,17 → 126,15 |
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); |
141,8 → 141,7 |
TV_SUB(&endtv, &starttv); |
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */ |
} |
return 1; |
return (1); |
} |
/* |
149,7 → 148,8 |
* `sleep' for the current turn time (using select). |
* Eat any input that might be available. |
*/ |
void tsleep(void) |
void |
tsleep(void) |
{ |
struct timeval tv; |
165,7 → 165,8 |
/* |
* getchar with timeout. |
*/ |
int tgetchar(void) |
int |
tgetchar(void) |
{ |
static struct timeval timeleft; |
char c; |
184,10 → 185,8 |
timeleft.tv_sec = 0; |
timeleft.tv_usec = fallrate; |
} |
if (!rwait(&timeleft)) |
return -1; |
return (-1); |
c = lastchar; |
lastchar = '\0'; |
return ((int) (unsigned char) c); |
195,3 → 194,4 |
/** @} |
*/ |
/branches/dd/uspace/app/tetris/scores.c |
---|
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) |
/* 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,27 → 101,33 |
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); |
124,19 → 134,17 |
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) |
169,8 → 177,7 |
} |
moveto(10, 28); |
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i, |
"........................................"); |
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................"); |
} |
scores[NUMSPOTS - 1].hs_score = score; |
180,9 → 187,9 |
while ((i > 0) && (scores[i - 1].hs_score < score)) |
i--; |
for (j = NUMSPOTS - 2; j > i; j--) |
for (j = NUMSPOTS - 2; j > i; j--) { |
copyhiscore(j, j-1); |
} |
copyhiscore(i, NUMSPOTS - 1); |
} |
196,5 → 203,371 |
} |
} |
/* |
* 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; */ |
/* 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); */ |
/* /\* */ |
/* * Grab a lock. */ |
/* *\/ */ |
/* if (flock(sd, lck)) */ |
/* warn("warning: score file %s cannot be locked", */ |
/* _PATH_SCOREFILE); */ |
/* 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); */ |
/* if (fpp) */ |
/* *fpp = sf; */ |
/* else */ |
/* (void)fclose(sf); */ |
/* } */ |
void |
savescore(int level) |
{ |
return; |
} |
/* struct highscore *sp; */ |
/* int i; */ |
/* int change; */ |
/* FILE *sf; */ |
/* const char *me; */ |
/* getscores(&sf); */ |
/* gotscores = 1; */ |
/* (void)time(&now); */ |
/* /\* */ |
/* * 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/dd/uspace/app/tetris/screen.c |
---|
50,21 → 50,18 |
#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 const struct shape *lastshape; |
/* |
* putstr() is for unpadded strings (either as in termcap(5) or |
* simply literal strings); |
75,19 → 72,19 |
putchar(*(s++)); |
} |
static void start_standout(uint32_t color) |
static void start_standout(void) |
{ |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, color); |
console_set_rgb_color(0xf0f0f0, 0); |
} |
static void resume_normal(void) |
{ |
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); |
} |
94,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(); |
} |
114,7 → 114,7 |
void moveto(int r, int c) |
{ |
console_goto(fphone(stdout), c, r); |
console_goto(r, c); |
} |
winsize_t winsize; |
121,25 → 121,23 |
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), |
155,33 → 153,33 |
/* |
* 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; |
cell *bp, *sp; |
cell so, cur_so = 0; |
int i, ccol, j; |
static const struct shape *lastshape; |
/* Always leave cursor after last displayed point */ |
/* always leave cursor after last displayed point */ |
curscreen[D_LAST * B_COLS - 1] = -1; |
if (score != curscore) { |
190,8 → 188,8 |
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; |
int tr, tc, t; |
198,22 → 196,18 |
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-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++) { |
236,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) { |
245,10 → 238,9 |
} |
moveto(RTOD(j), CTOD(i)); |
} |
if (so != cur_so) { |
if (so) |
start_standout(so); |
start_standout(); |
else |
resume_normal(); |
cur_so = so; |
264,22 → 256,19 |
* `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); |
} |
287,12 → 276,13 |
* 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 |
302,3 → 292,4 |
/** @} |
*/ |
/branches/dd/uspace/app/tetris/scores.h |
---|
34,7 → 34,6 |
* |
* @(#)scores.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
45,25 → 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) |
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 */ |
// time_t hs_time; /* time at game end */ |
}; |
extern void showscores(int); |
extern void initscores(void); |
extern void insertscore(int score, int level); |
#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/dd/uspace/app/tetris/tetris.c |
---|
42,18 → 42,24 |
/** @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 <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <getopt.h> |
#include "input.h" |
#include "scores.h" |
61,50 → 67,45 |
#include "tetris.h" |
cell board[B_SIZE]; |
int Rows; |
int Cols; |
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; |
int classic; |
int showpreview, classic; |
static void elide(void); |
static void setup_board(void); |
static const struct shape *randshape(void); |
const struct shape *randshape(void); |
void onintr(int); |
void usage(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 |
* 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++) { |
112,24 → 113,19 |
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; |
148,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]; |
return (tmp); |
} |
192,10 → 189,28 |
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; |
204,6 → 219,7 |
printf("on "); |
else |
printf("off"); |
break; |
case 'h': |
showscores(firstgame); |
229,62 → 245,73 |
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: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(); |
} |
/* 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; |
/* argc -= optind; */ |
/* argv += optind; */ |
if (argc) |
usage(); |
/* if (argc) */ |
/* usage(); */ |
for (i = 0; i <= 5; i++) { |
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'; |
291,7 → 318,7 |
} |
} |
snprintf(key_msg, sizeof(key_msg), |
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]); |
313,7 → 340,7 |
scr_msg(key_msg, 1); |
while (1) { |
for (;;) { |
place(curshape, pos, 1); |
scr_update(); |
place(curshape, pos, 0); |
342,10 → 369,8 |
curshape = nextshape; |
nextshape = randshape(); |
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1; |
if (!fits_in(curshape, pos)) |
break; |
continue; |
} |
356,7 → 381,6 |
/* quit */ |
break; |
} |
if (c == keys[4]) { |
static char msg[] = |
"paused - press RETURN to continue"; |
368,13 → 392,11 |
scr_msg(msg, 1); |
(void) fflush(stdout); |
} 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)) |
381,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)) |
398,7 → 418,6 |
pos++; |
continue; |
} |
if (c == keys[3]) { |
/* move to bottom */ |
while (fits_in(curshape, pos + B_COLS)) { |
407,7 → 426,6 |
} |
continue; |
} |
if (c == '\f') { |
scr_clear(); |
scr_msg(key_msg, 1); |
420,17 → 438,32 |
} |
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/dd/uspace/app/tetris/screen.h |
---|
46,27 → 46,26 |
*/ |
#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/dd/uspace/app/tetris/tetris.h |
---|
55,20 → 55,19 |
* worrying about addressing problems. |
*/ |
/* The board */ |
/* 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 */ |
/* The displayed area (rows) */ |
/* the displayed area (rows) */ |
#define D_FIRST 1 |
#define D_LAST 22 |
/* The active area (rows) */ |
/* the active area (rows) */ |
#define A_FIRST 1 |
#define A_LAST 21 |
78,9 → 77,7 |
#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. |
134,7 → 131,6 |
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; |
}; |
extern const struct shape shapes[]; |
153,7 → 149,6 |
* but by then the game is utterly impossible. |
*/ |
extern long fallrate; /* less than 1 million; smaller => faster */ |
#define faster() (fallrate -= fallrate / 3000) |
/* |
177,15 → 172,17 |
*/ |
#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 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/dd/uspace/app/tetris/shapes.c |
---|
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 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 BL B_COLS-1 /* bottom left */ |
#define BC B_COLS /* bottom center */ |
#define BR (B_COLS + 1) /* bottom right */ |
#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/dd/uspace/app/tetris/input.h |
---|
41,9 → 41,10 |
/** @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/dd/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/dd/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" |
/* 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/dd/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,13 |
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("write", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_WRITE, o); |
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CLEAR, o); |
674,7 → 677,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/dd/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/dd/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/dd/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" |