/branches/network/uspace/app/bdsh/input.c |
---|
61,7 → 61,7 |
if (NULL == usr->line) |
return CL_EFAIL; |
tmp = strdup(usr->line); |
tmp = str_dup(usr->line); |
cmd[n] = strtok(tmp, " "); |
while (cmd[n] && n < WORD_MAX) { |
146,7 → 146,6 |
void get_input(cliuser_t *usr) |
{ |
char line[INPUT_MAX]; |
size_t len = 0; |
console_set_style(STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
153,11 → 152,10 |
console_set_style(STYLE_NORMAL); |
read_line(line, INPUT_MAX); |
len = strlen(line); |
/* Make sure we don't have rubbish or a C/R happy user */ |
if (len == 0 || line[0] == '\n') |
if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0) |
return; |
usr->line = strdup(line); |
usr->line = str_dup(line); |
return; |
} |
/branches/network/uspace/app/bdsh/cmds/mod_cmds.c |
---|
64,7 → 64,7 |
return -2; |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!strcmp(mod->name, command)) |
if (!str_cmp(mod->name, command)) |
return i; |
} |
81,7 → 81,7 |
return -1; |
for(i=0; mod_aliases[i] != NULL; i+=2) { |
if (!strcmp(mod_aliases[i], command)) |
if (!str_cmp(mod_aliases[i], command)) |
return 1; |
} |
97,7 → 97,7 |
return (char *)NULL; |
for(i=0; mod_aliases[i] != NULL; i++) { |
if (!strcmp(mod_aliases[i], command)) |
if (!str_cmp(mod_aliases[i], command)) |
return (char *)mod_aliases[++i]; |
i++; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch.c |
---|
80,7 → 80,7 |
} |
for (i = 1; i < argc; i ++) { |
buff = strdup(argv[i]); |
buff = str_dup(argv[i]); |
dirp = opendir(buff); |
if (dirp) { |
cli_error(CL_ENOTSUP, "%s is a directory", buff); |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c |
---|
93,7 → 93,7 |
/* Its a good idea to allocate path, plus we (may) need a copy of |
* path to tokenize if parents are specified */ |
if (NULL == (tmp = strdup(path))) { |
if (NULL == (tmp = str_dup(path))) { |
cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
return 1; |
} |
149,7 → 149,7 |
while (dirs[i] != NULL) { |
/* Sometimes make or scripts conjoin odd paths. Account for something |
* like this: ../../foo/bar/../foo/foofoo/./bar */ |
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) { |
if (!str_cmp(dirs[i], "..") || !str_cmp(dirs[i], ".")) { |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: impossible path: %s", |
cmdname, path); |
/branches/network/uspace/app/bdsh/cmds/modules/help/help.c |
---|
107,7 → 107,7 |
} |
if (argc == 3) { |
if (!strcmp("extended", argv[2])) |
if (!str_cmp("extended", argv[2])) |
level = HELP_LONG; |
else |
level = HELP_SHORT; |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
182,7 → 182,7 |
if (argc == 1) |
getcwd(buff, PATH_MAX); |
else |
strncpy(buff, argv[1], PATH_MAX); |
str_cpy(buff, PATH_MAX, argv[1]); |
scope = ls_scope(buff); |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
216,7 → 216,7 |
i = optind; |
while (NULL != argv[i]) { |
len = strlen(argv[i]) + 2; |
len = str_size(argv[i]) + 2; |
buff = (char *) realloc(buff, len); |
if (buff == NULL) { |
printf("rm: out of memory\n"); |
/branches/network/uspace/app/bdsh/cmds/builtin_cmds.c |
---|
49,7 → 49,7 |
return -2; |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!strcmp(cmd->name, command)) |
if (!str_cmp(cmd->name, command)) |
return i; |
} |
64,7 → 64,7 |
return -1; |
for(i=0; builtin_aliases[i] != NULL; i+=2) { |
if (!strcmp(builtin_aliases[i], command)) |
if (!str_cmp(builtin_aliases[i], command)) |
return 1; |
} |
79,7 → 79,7 |
return (char *)NULL; |
for(i=0; builtin_aliases[i] != NULL; i++) { |
if (!strcmp(builtin_aliases[i], command)) |
if (!str_cmp(builtin_aliases[i], command)) |
return (char *)builtin_aliases[++i]; |
i++; |
} |
/branches/network/uspace/app/bdsh/exec.c |
---|
71,7 → 71,7 |
char *path_tok; |
char *path[PATH_MAX]; |
int n = 0, i = 0; |
size_t x = strlen(cmd) + 2; |
size_t x = str_size(cmd) + 2; |
found = (char *)malloc(PATH_MAX); |
80,12 → 80,12 |
return (char *) cmd; |
} |
path_tok = strdup(PATH); |
path_tok = str_dup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
if ((strlen(path[n]) + x ) > PATH_MAX) { |
if ((str_size(path[n]) + x ) > PATH_MAX) { |
cli_error(CL_ENOTSUP, |
"Segment %d of path is too large, search ends at segment %d", |
n, n-1); |
114,7 → 114,7 |
task_id_t tid; |
char *tmp; |
tmp = strdup(find_command(cmd)); |
tmp = str_dup(find_command(cmd)); |
free(found); |
tid = task_spawn((const char *)tmp, argv); |
/branches/network/uspace/app/init/init.c |
---|
45,6 → 45,7 |
#include <malloc.h> |
#include <macros.h> |
#include <console.h> |
#include <string.h> |
#include "init.h" |
#include "version.h" |
51,9 → 52,13 |
static bool mount_fs(const char *fstype) |
{ |
int rc = -1; |
char *opts = ""; |
if (str_cmp(fstype, "tmpfs") == 0) |
opts = "restore"; |
while (rc < 0) { |
rc = mount(fstype, "/", "initrd", IPC_FLAG_BLOCKING); |
rc = mount(fstype, "/", "initrd", opts, IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
83,13 → 88,9 |
argv[0] = fname; |
argv[1] = NULL; |
if (task_spawn(fname, argv)) { |
/* Add reasonable delay to avoid intermixed klog output. */ |
usleep(10000); |
} else { |
if (!task_spawn(fname, argv)) |
printf(NAME ": Error spawning %s\n", fname); |
} |
} |
int main(int argc, char *argv[]) |
{ |
/branches/network/uspace/app/tester/devmap/devmap1.c |
---|
140,7 → 140,7 |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *)name, strlen(name) + 1); |
retval = ipc_data_write_start(phone, (char *)name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
173,7 → 173,7 |
req = async_send_2(driver_phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, |
&answer); |
retval = ipc_data_write_start(driver_phone, name, strlen(name) + 1); |
retval = ipc_data_write_start(driver_phone, name, str_size(name) + 1); |
if (retval != EOK) { |
printf("Failed to send device name '%s'.\n", name); |
215,7 → 215,7 |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *)name, |
strlen(name) + 1); |
str_size(name) + 1); |
if (retval != EOK) { |
printf("Failed to send device name '%s'.\n", name); |
/branches/network/uspace/app/tester/vfs/vfs1.c |
---|
45,7 → 45,7 |
{ |
int rc; |
rc = mount("tmpfs", "/", "nulldev0", 0); |
rc = mount("tmpfs", "/", "nulldev0", "", 0); |
switch (rc) { |
case EOK: |
if (!quiet) |
/branches/network/uspace/app/tetris/scores.c |
---|
117,7 → 117,8 |
*/ |
static void copyhiscore(int dest, int src) |
{ |
strcpy(scores[dest].hs_name, scores[src].hs_name); |
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; |
} |
131,7 → 132,8 |
clear_screen(); |
moveto(10 , 10); |
puts("Insert your name: "); |
strncpy(scores[NUMSPOTS - 1].hs_name, "Player", MAXLOGNAME); |
str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, |
"Player"); |
i = 6; off = 6; |
moveto(10 , 28); |
195,7 → 197,7 |
{ |
int i; |
for(i = 0; i < NUMSPOTS; i++) { |
strncpy(scores[i].hs_name, "HelenOS Team", MAXLOGNAME); |
str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team"); |
scores[i].hs_score = (NUMSPOTS - i) * 200; |
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1); |
} |
289,7 → 291,7 |
/* change = 0; */ |
/* me = thisuser(); */ |
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */ |
/* if (sp->hs_level != level || strcmp(sp->hs_name, me) != 0) */ |
/* 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", */ |
417,7 → 419,7 |
/* * This is O(n^2), but do you think we care? */ |
/* *\/ */ |
/* for (j = 0, pu = count; j < numnames; j++, pu++) */ |
/* if (strcmp(sp->hs_name, pu->name) == 0) */ |
/* if (str_cmp(sp->hs_name, pu->name) == 0) */ |
/* break; */ |
/* if (j == numnames) { */ |
/* /\* */ |
554,7 → 556,7 |
/* if (me != NULL && */ |
/* sp->hs_level == level && */ |
/* sp->hs_score == score && */ |
/* strcmp(sp->hs_name, me) == 0) { */ |
/* str_cmp(sp->hs_name, me) == 0) { */ |
/* putpad(SOstr); */ |
/* highlight = 1; */ |
/* } */ |
/branches/network/uspace/app/tetris/input.c |
---|
115,7 → 115,7 |
if (!lastchar) { |
again: |
if (!getchar_inprog) { |
cons_phone = console_phone_get(true); |
cons_phone = console_open(true); |
getchar_inprog = async_send_2(cons_phone, |
CONSOLE_GETKEY, 0, 0, &charcall); |
} |
/branches/network/uspace/app/tetris/screen.c |
---|
280,7 → 280,7 |
scr_msg(char *s, int set) |
{ |
int l = strlen(s); |
int l = str_size(s); |
moveto(Rows - 2, ((Cols - l) >> 1) - 1); |
if (set) |
/branches/network/uspace/app/tetris/tetris.c |
---|
277,7 → 277,7 |
/* classic = 1; */ |
/* break; */ |
/* case 'k': */ |
/* if (strlen(keys = optarg) != 6) */ |
/* if (str_size(keys = optarg) != 6) */ |
/* usage(); */ |
/* break; */ |
/* case 'l': */ |
311,7 → 311,7 |
errx(1, "duplicate command keys specified."); |
} |
if (keys[i] == ' ') |
strncpy(key_write[i], "<space>", sizeof key_write[i]); |
str_cpy(key_write[i], sizeof key_write[i], "<space>"); |
else { |
key_write[i][0] = keys[i]; |
key_write[i][1] = '\0'; |
/branches/network/uspace/lib/libc/include/console.h |
---|
40,17 → 40,15 |
#include <sys/types.h> |
#include <bool.h> |
extern void console_open(bool); |
extern int console_open(bool); |
extern void console_close(void); |
extern int console_phone_get(bool); |
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 *buf, size_t nbyte); |
extern void console_putstr(const char *s); |
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 *); |
/branches/network/uspace/lib/libc/include/string.h |
---|
45,8 → 45,8 |
/**< No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/**< Maximum size of a string containing cnt characters */ |
#define STR_BOUNDS(cnt) (cnt << 2) |
/**< Maximum size of a string containing @c length characters */ |
#define STR_BOUNDS(length) ((length) << 2) |
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz); |
extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz); |
69,34 → 69,26 |
extern int str_cmp(const char *s1, const char *s2); |
extern int str_lcmp(const char *s1, const char *s2, count_t max_len); |
extern void str_ncpy(char *dst, const char *src, size_t size); |
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); |
extern void str_append(char *dest, size_t size, const char *src); |
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); |
extern const char *str_chr(const char *str, wchar_t ch); |
extern const char *str_rchr(const char *str, wchar_t ch); |
extern 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 *); |
/* |
* TODO: Get rid of this. |
*/ |
extern int strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
extern char *strcpy(char *, const char *); |
extern char *strncpy(char *, const char *, size_t); |
extern char *strcat(char *, const char *); |
extern size_t strlen(const char *); |
extern char *strdup(const char *); |
extern char *strchr(const char *, int); |
extern char *strrchr(const char *, int); |
extern long int strtol(const char *, char **, int); |
extern unsigned long strtoul(const char *, char **, int); |
/branches/network/uspace/lib/libc/include/vfs/vfs.h |
---|
39,7 → 39,7 |
extern char *absolutize(const char *, size_t *); |
extern int mount(const char *, const char *, const char *, |
extern int mount(const char *, const char *, const char *, const char *, |
const unsigned int flags); |
#endif |
/branches/network/uspace/lib/libc/include/async.h |
---|
98,22 → 98,22 |
/* Wrappers for simple communication */ |
#define async_msg_0(phone, method) \ |
ipc_call_async_0((phone), (method), NULL, NULL, !in_interrupt_handler()) |
ipc_call_async_0((phone), (method), NULL, NULL, true) |
#define async_msg_1(phone, method, arg1) \ |
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_2(phone, method, arg1, arg2) \ |
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_3(phone, method, arg1, arg2, arg3) \ |
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \ |
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, !in_interrupt_handler()) |
NULL, true) |
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \ |
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, !in_interrupt_handler()) |
(arg5), NULL, NULL, true) |
/* |
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros |
253,8 → 253,6 |
fibril_dec_sercount(); |
} |
extern bool in_interrupt_handler(void); |
extern atomic_t async_futex; |
#endif |
/branches/network/uspace/lib/libc/include/stdio.h |
---|
49,7 → 49,7 |
int n; \ |
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \ |
if (n > 0) \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, strlen(buf)); \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, str_size(buf)); \ |
} |
typedef struct { |
/branches/network/uspace/lib/libc/include/thread.h |
---|
45,7 → 45,7 |
extern void __thread_main(uspace_arg_t *); |
extern int thread_create(void (*)(void *), void *, char *, thread_id_t *); |
extern void thread_exit(int); |
extern void thread_exit(int) __attribute__ ((noreturn)); |
extern void thread_detach(thread_id_t); |
extern int thread_join(thread_id_t); |
extern thread_id_t thread_get_id(void); |
/branches/network/uspace/lib/libc/include/io/stream.h |
---|
39,13 → 39,9 |
#define EMFILE -17 |
extern ssize_t read_stdin(void *, size_t); |
extern void klog_update(void); |
extern ssize_t read_stdin(void *, size_t); |
extern ssize_t write_stdout(const void *, size_t); |
extern ssize_t write_stderr(const void *, size_t); |
extern int flush_stdout(void); |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/ipc/fb.h |
---|
66,7 → 66,9 |
FB_ANIM_CHGVP, |
FB_ANIM_START, |
FB_ANIM_STOP, |
FB_POINTER_MOVE |
FB_POINTER_MOVE, |
FB_SCREEN_YIELD, |
FB_SCREEN_RECLAIM |
} fb_request_t; |
#endif |
/branches/network/uspace/lib/libc/generic/kbd.c |
---|
42,7 → 42,7 |
int kbd_get_event(kbd_event_t *ev) |
{ |
int cons_phone = console_phone_get(true); |
int cons_phone = console_open(true); |
ipcarg_t r0, r1, r2, r3; |
int rc; |
/branches/network/uspace/lib/libc/generic/console.c |
---|
34,6 → 34,7 |
/** @file |
*/ |
#include <libc.h> |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
56,86 → 57,50 |
/** Pointer to first available field in cbuffer. */ |
static char *cbp = cbuffer; |
static ssize_t cons_write(const char *buf, size_t nbyte); |
static void cons_putchar(wchar_t c); |
static void cbuffer_flush(void); |
static void cbuffer_drain(void); |
static inline void cbuffer_putc(int c); |
void console_open(bool blocking) |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
{ |
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); |
console_wait(); |
async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
} |
if (phone >= 0) |
console_phone = phone; |
} |
} |
void console_close(void) |
/** 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) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
} |
} |
} |
async_serialize_start(); |
int console_phone_get(bool blocking) |
{ |
if (console_phone < 0) |
console_open(blocking); |
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); |
return console_phone; |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
void console_wait(void) |
{ |
while (console_phone < 0) |
console_open(true); |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_drain(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); |
} |
void console_goto(int row, int col) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
void console_putchar(wchar_t c) |
{ |
// cbuffer_putc(c); |
cbuffer_flush(); |
cons_putchar(c); |
} |
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
{ |
int rc; |
int len; |
size_t len = cbp - cbuffer; |
len = cbp - cbuffer; |
while (len > 0) { |
rc = cons_write(cbuffer, cbp - cbuffer); |
ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
152,7 → 117,7 |
} |
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(int c) |
static inline void cbuffer_putc(char c) |
{ |
if (cbp == cbuffer_end) |
cbuffer_flush(); |
163,88 → 128,53 |
cbuffer_flush(); |
} |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
int console_open(bool blocking) |
{ |
int cons_phone = console_phone_get(true); |
async_msg_1(cons_phone, CONSOLE_PUTCHAR, c); |
} |
if (console_phone < 0) { |
int phone; |
/** Write characters to the console via IPC. */ |
static ssize_t cons_write(const char *buf, size_t nbyte) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
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); |
async_serialize_start(); |
req = async_send_0(cons_phone, CONSOLE_WRITE, &answer); |
rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
if (phone >= 0) |
console_phone = phone; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return console_phone; |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t nbyte) |
void console_close(void) |
{ |
size_t left; |
left = nbyte; |
while (left > 0) { |
cbuffer_putc(*buf++); |
--left; |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) |
console_phone = -1; |
} |
return nbyte; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *s) |
void console_wait(void) |
{ |
size_t len; |
ssize_t rc; |
len = strlen(s); |
while (len > 0) { |
rc = console_write(s, len); |
if (rc < 0) |
return; /* Error */ |
s += rc; |
len -= rc; |
while (console_phone < 0) |
console_open(true); |
} |
} |
/** Flush all output to the console. */ |
void console_flush(void) |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(false); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
console_wait(); |
cbuffer_drain(); |
async_msg_0(console_phone, CONSOLE_CLEAR); |
} |
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t r, c; |
int rc; |
console_wait(); |
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
ipcarg_t r; |
ipcarg_t c; |
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c); |
*rows = (int) r; |
*cols = (int) c; |
254,43 → 184,91 |
void console_set_style(int style) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
async_msg_1(console_phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int show) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
void console_kcon_enable(void) |
{ |
int cons_phone = console_phone_get(true); |
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_0(cons_phone, CONSOLE_KCON_ENABLE); |
async_msg_2(console_phone, CONSOLE_GOTO, row, col); |
} |
void console_putchar(wchar_t c) |
{ |
console_wait(); |
cbuffer_flush(); |
cons_putchar(c); |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t size) |
{ |
size_t left = size; |
while (left > 0) { |
cbuffer_putc(*buf++); |
left--; |
} |
return size; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *str) |
{ |
size_t left = str_size(str); |
while (left > 0) { |
ssize_t rc = console_write(str, left); |
if (rc < 0) { |
/* Error */ |
return; |
} |
str += rc; |
left -= rc; |
} |
} |
/** Flush all output to the console or klog. */ |
void console_flush(void) |
{ |
cbuffer_flush(); |
if (console_phone >= 0) |
async_msg_0(console_phone, CONSOLE_FLUSH); |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/getopt.c |
---|
241,7 → 241,7 |
} |
} |
if ((optchar = (int)*place++) == (int)':' || |
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
(oli = str_chr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
/* option letter unknown or ':' */ |
if (!*place) |
++optind; |
377,20 → 377,20 |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
if ((has_equal = str_chr(current_argv, '=')) != NULL) { |
/* argument found (--option=arg) */ |
current_argv_len = has_equal - current_argv; |
has_equal++; |
} else |
current_argv_len = strlen(current_argv); |
current_argv_len = str_size(current_argv); |
for (i = 0; long_options[i].name; i++) { |
/* find matching long option */ |
if (strncmp(current_argv, long_options[i].name, |
current_argv_len)) |
if (str_lcmp(current_argv, long_options[i].name, |
str_nlength(current_argv, current_argv_len))) |
continue; |
if (strlen(long_options[i].name) == |
if (str_size(long_options[i].name) == |
(unsigned)current_argv_len) { |
/* exact match */ |
match = i; |
/branches/network/uspace/lib/libc/generic/string.c |
---|
35,11 → 35,13 |
#include <string.h> |
#include <stdlib.h> |
#include <assert.h> |
#include <limits.h> |
#include <ctype.h> |
#include <malloc.h> |
#include <errno.h> |
#include <align.h> |
#include <mem.h> |
#include <string.h> |
/** Byte mask consisting of lowest @n bits (out of 8) */ |
461,40 → 463,91 |
} |
/** Copy NULL-terminated string. |
/** Copy string. |
* |
* Copy source string @a src to destination buffer @a dst. |
* No more than @a size bytes are written. NULL-terminator is always |
* written after the last succesfully copied character (i.e. if the |
* destination buffer is has at least 1 byte, it will be always |
* NULL-terminated). |
* Copy source string @a src to destination buffer @a dest. |
* No more than @a size bytes are written. If the size of the output buffer |
* is at least one byte, the output string will always be well-formed, i.e. |
* null-terminated and containing only complete characters. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
*/ |
void str_cpy(char *dest, size_t size, const char *src) |
{ |
wchar_t ch; |
size_t src_off; |
size_t dest_off; |
/* There must be space for a null terminator in the buffer. */ |
assert(size > 0); |
src_off = 0; |
dest_off = 0; |
while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
dest[dest_off] = '\0'; |
} |
/** Copy size-limited substring. |
* |
* Copy prefix of string @a src of max. size @a size to destination buffer |
* @a dest. No more than @a size bytes are written. The output string will |
* always be well-formed, i.e. null-terminated and containing only complete |
* characters. |
* |
* No more than @a n bytes are read from the input string, so it does not |
* have to be null-terminated. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer. |
* |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
* @param n Maximum number of bytes to read from @a src. |
*/ |
void str_ncpy(char *dst, const char *src, size_t size) |
void str_ncpy(char *dest, size_t size, const char *src, size_t n) |
{ |
/* No space for the NULL-terminator in the buffer */ |
if (size == 0) |
return; |
wchar_t ch; |
size_t str_off = 0; |
size_t dst_off = 0; |
size_t src_off; |
size_t dest_off; |
while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) { |
if (chr_encode(ch, dst, &dst_off, size) != EOK) |
/* There must be space for a null terminator in the buffer. */ |
assert(size > 0); |
src_off = 0; |
dest_off = 0; |
while ((ch = str_decode(src, &src_off, n)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
if (dst_off >= size) |
dst[size - 1] = 0; |
else |
dst[dst_off] = 0; |
dest[dest_off] = '\0'; |
} |
/** Append one string to another. |
* |
* Append source string @a src to string in destination buffer @a dest. |
* Size of the destination buffer is @a dest. If the size of the output buffer |
* is at least one byte, the output string will always be well-formed, i.e. |
* null-terminated and containing only complete characters. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer. |
* @param src Source string. |
*/ |
void str_append(char *dest, size_t size, const char *src) |
{ |
size_t dstr_size; |
dstr_size = str_size(dest); |
str_cpy(dest + dstr_size, size - dstr_size, src); |
} |
/** Copy NULL-terminated wide string to string |
* |
* Copy source wide string @a src to destination buffer @a dst. |
535,21 → 588,45 |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
* |
*/ |
const char *str_chr(const char *str, wchar_t ch) |
{ |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + off); |
return (str + last); |
last = off; |
} |
return NULL; |
} |
/** Find last occurence of character in string. |
* |
* @param str String to search. |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
const char *str_rchr(const char *str, wchar_t ch) |
{ |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
char *res = NULL; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
res = (str + last); |
last = off; |
} |
return res; |
} |
/** Insert a wide character into a wide string. |
* |
* Insert a wide character into a wide string at position |
606,42 → 683,6 |
return true; |
} |
/** Count the number of characters in the string, not including terminating 0. |
* |
* @param str String. |
* @return Number of characters in string. |
*/ |
size_t strlen(const char *str) |
{ |
size_t counter = 0; |
while (str[counter] != 0) |
counter++; |
return counter; |
} |
int strcmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
return (a[c] - b[c]); |
} |
int strncmp(const char *a, const char *b, size_t n) |
{ |
size_t c = 0; |
while (c < n && a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
return ( c < n ? a[c] - b[c] : 0); |
} |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
652,44 → 693,6 |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Return pointer to the first occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strchr(const char *str, int c) |
{ |
while (*str != '\0') { |
if (*str == (char) c) |
return (char *) str; |
str++; |
} |
return NULL; |
} |
/** Return pointer to the last occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strrchr(const char *str, int c) |
{ |
char *retval = NULL; |
while (*str != '\0') { |
if (*str == (char) c) |
retval = (char *) str; |
str++; |
} |
return (char *) retval; |
} |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* |
839,44 → 842,15 |
return (sgn ? -number : number); |
} |
char *strcpy(char *dest, const char *src) |
char *str_dup(const char *src) |
{ |
char *orig = dest; |
size_t size = str_size(src); |
void *dest = malloc(size + 1); |
while ((*(dest++) = *(src++))) |
; |
return orig; |
} |
char *strncpy(char *dest, const char *src, size_t n) |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++)) && --n) |
; |
return orig; |
} |
char *strcat(char *dest, const char *src) |
{ |
char *orig = dest; |
while (*dest++) |
; |
--dest; |
while ((*dest++ = *src++)) |
; |
return orig; |
} |
char * strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
if (dest == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
return (char *) memcpy(dest, src, size + 1); |
} |
char *strtok(char *s, const char *delim) |
894,11 → 868,11 |
s = *next; |
/* Skip over leading delimiters. */ |
while (*s && (strchr(delim, *s) != NULL)) ++s; |
while (*s && (str_chr(delim, *s) != NULL)) ++s; |
start = s; |
/* Skip over token characters. */ |
while (*s && (strchr(delim, *s) == NULL)) ++s; |
while (*s && (str_chr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
/branches/network/uspace/lib/libc/generic/loader.c |
---|
180,7 → 180,7 |
dp = arg_buf; |
while (*ap != NULL) { |
str_ncpy(dp, *ap, buffer_size - (dp - arg_buf)); |
str_cpy(dp, buffer_size - (dp - arg_buf), *ap); |
dp += str_size(*ap) + 1; |
++ap; |
/branches/network/uspace/lib/libc/generic/thread.c |
---|
130,6 → 130,8 |
void thread_exit(int status) |
{ |
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status); |
for (;;) |
; |
} |
/** Detach thread. |
152,6 → 154,7 |
*/ |
int thread_join(thread_id_t thread) |
{ |
return 0; |
} |
/** Get current thread ID. |
/branches/network/uspace/lib/libc/generic/libc.c |
---|
48,6 → 48,7 |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <console.h> |
#include <loader/pcb.h> |
extern char _heap; |
83,6 → 84,7 |
} |
main(argc, argv); |
console_flush(); |
} |
void __exit(void) |
/branches/network/uspace/lib/libc/generic/async.c |
---|
35,14 → 35,15 |
/** |
* Asynchronous library |
* |
* The aim of this library is facilitating writing programs utilizing the |
* asynchronous nature of HelenOS IPC, yet using a normal way of programming. |
* The aim of this library is to provide a facility for writing programs which |
* utilize the asynchronous nature of HelenOS IPC, yet using a normal way of |
* programming. |
* |
* You should be able to write very simple multithreaded programs, the async |
* framework will automatically take care of most synchronization problems. |
* |
* Default semantics: |
* - async_send_*(): send asynchronously. If the kernel refuses to send |
* - async_send_*(): Send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* |
66,12 → 67,12 |
* |
* |
* 2) Multithreaded server application |
* |
* main() |
* { |
* async_manager(); |
* } |
* |
* |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
85,7 → 86,7 |
* ipc_answer_2(callid, 1, 2, 3); |
* |
* callid = async_get_call(&call); |
* .... |
* ... |
* } |
* |
*/ |
104,24 → 105,26 |
#include <bool.h> |
atomic_t async_futex = FUTEX_INITIALIZER; |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
/** Structures of this type represent a waiting fibril. */ |
typedef struct { |
/** Expiration time. */ |
struct timeval expires; |
/** If true, this struct is in the timeout list. */ |
int inlist; |
bool inlist; |
/** Timeout list link. */ |
link_t link; |
/** Identification of and link to the waiting fibril. */ |
fid_t fid; |
/** If true, this fibril is currently active. */ |
int active; |
bool active; |
/** If true, we have timed out. */ |
int timedout; |
bool timedout; |
} awaiter_t; |
typedef struct { |
128,7 → 131,8 |
awaiter_t wdata; |
/** If reply was received. */ |
int done; |
bool done; |
/** Pointer to where the answer data is stored. */ |
ipc_call_t *dataptr; |
172,12 → 176,6 |
/** Identifier of the incoming connection handled by the current fibril. */ |
__thread connection_t *FIBRIL_connection; |
/** |
* If true, it is forbidden to use async_req functions and all preemption is |
* disabled. |
*/ |
__thread int _in_interrupt_handler; |
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); |
185,6 → 183,7 |
* Pointer to a fibril function that will be used to handle connections. |
*/ |
static async_client_conn_t client_connection = default_client_connection; |
/** |
* Pointer to a fibril function that will be used to handle interrupt |
* notifications. |
191,17 → 190,11 |
*/ |
static async_client_conn_t interrupt_received = default_interrupt_received; |
/* |
* Getter for _in_interrupt_handler. We need to export the value of this thread |
* local variable to other modules, but the binutils 2.18 linkers die on an |
* attempt to export this symbol in the header file. For now, consider this as a |
* workaround. |
*/ |
bool in_interrupt_handler(void) |
{ |
return _in_interrupt_handler; |
} |
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. |
209,11 → 202,12 |
* @param key Pointer to source phone hash. |
* |
* @return Index into the connection hash table. |
* |
*/ |
static hash_index_t conn_hash(unsigned long *key) |
{ |
assert(key); |
return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS); |
} |
/** Compare hash table item with a key. |
223,14 → 217,12 |
* @param item Connection hash table item. |
* |
* @return True on match, false otherwise. |
* |
*/ |
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
connection_t *hs; |
hs = hash_table_get_instance(item, connection_t, link); |
return key[0] == hs->in_phone_hash; |
connection_t *hs = hash_table_get_instance(item, connection_t, link); |
return (key[0] == hs->in_phone_hash); |
} |
/** Connection hash table removal callback function. |
239,6 → 231,7 |
* hash table. |
* |
* @param item Connection hash table item being removed. |
* |
*/ |
static void conn_remove(link_t *item) |
{ |
256,22 → 249,23 |
/** Sort in current fibril's timeout request. |
* |
* @param wd Wait data of the current fibril. |
* |
*/ |
static void insert_timeout(awaiter_t *wd) |
{ |
link_t *tmp; |
awaiter_t *cur; |
wd->timedout = false; |
wd->inlist = true; |
wd->timedout = 0; |
wd->inlist = 1; |
link_t *tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
awaiter_t *cur = list_get_instance(tmp, awaiter_t, link); |
tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
cur = list_get_instance(tmp, awaiter_t, link); |
if (tv_gteq(&cur->expires, &wd->expires)) |
break; |
tmp = tmp->next; |
} |
list_append(&wd->link, tmp); |
} |
284,28 → 278,30 |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return Zero if the call doesn't match any connection. |
* One if the call was passed to the respective connection |
* fibril. |
* @return False if the call doesn't match any connection. |
* True if the call was passed to the respective connection fibril. |
* |
*/ |
static int route_call(ipc_callid_t callid, ipc_call_t *call) |
static bool route_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
connection_t *conn; |
msg_t *msg; |
link_t *hlp; |
unsigned long key; |
futex_down(&async_futex); |
key = call->in_phone_hash; |
hlp = hash_table_find(&conn_hash_table, &key); |
unsigned long key = call->in_phone_hash; |
link_t *hlp = hash_table_find(&conn_hash_table, &key); |
if (!hlp) { |
futex_up(&async_futex); |
return 0; |
return false; |
} |
conn = hash_table_get_instance(hlp, connection_t, link); |
msg = malloc(sizeof(*msg)); |
connection_t *conn = hash_table_get_instance(hlp, connection_t, link); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
list_append(&msg->link, &conn->msg_queue); |
315,20 → 311,71 |
/* If the connection fibril is waiting for an event, activate it */ |
if (!conn->wdata.active) { |
/* If in timeout list, remove it */ |
if (conn->wdata.inlist) { |
conn->wdata.inlist = 0; |
conn->wdata.inlist = false; |
list_remove(&conn->wdata.link); |
} |
conn->wdata.active = 1; |
conn->wdata.active = true; |
fibril_add_ready(conn->wdata.fid); |
} |
futex_up(&async_futex); |
return true; |
} |
return 1; |
/** Notification fibril. |
* |
* When a notification arrives, a fibril with this implementing function is |
* created. It calls interrupt_received() and does the final cleanup. |
* |
* @param arg Message structure pointer. |
* |
* @return Always zero. |
* |
*/ |
static int notification_fibril(void *arg) |
{ |
msg_t *msg = (msg_t *) arg; |
interrupt_received(msg->callid, &msg->call); |
free(msg); |
return 0; |
} |
/** Process interrupt notification. |
* |
* A new fibril is created which would process the notification. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return False if an error occured. |
* True if the call was passed to the notification fibril. |
* |
*/ |
static bool process_notification(ipc_callid_t callid, ipc_call_t *call) |
{ |
futex_down(&async_futex); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
fid_t fid = fibril_create(notification_fibril, msg); |
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. |
339,20 → 386,19 |
* then a hash of the incoming call is returned unless |
* the timeout expires prior to receiving a message. In |
* that case zero is returned. |
* |
*/ |
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
{ |
msg_t *msg; |
ipc_callid_t callid; |
connection_t *conn; |
assert(FIBRIL_connection); |
assert(FIBRIL_connection); |
/* GCC 4.1.0 coughs on FIBRIL_connection-> dereference, |
/* Why doing this? |
* GCC 4.1.0 coughs on FIBRIL_connection-> dereference. |
* GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. |
* I would never expect to find so many errors in |
* a compiler *($&$(*&$ |
* a compiler. |
*/ |
conn = FIBRIL_connection; |
connection_t *conn = FIBRIL_connection; |
futex_down(&async_futex); |
359,15 → 405,16 |
if (usecs) { |
gettimeofday(&conn->wdata.expires, NULL); |
tv_add(&conn->wdata.expires, usecs); |
} else { |
conn->wdata.inlist = 0; |
} |
} else |
conn->wdata.inlist = false; |
/* If nothing in queue, wait until something arrives */ |
while (list_empty(&conn->msg_queue)) { |
if (usecs) |
insert_timeout(&conn->wdata); |
conn->wdata.active = 0; |
conn->wdata.active = false; |
/* |
* Note: the current fibril will be rescheduled either due to a |
* timeout or due to an arriving message destined to it. In the |
375,13 → 422,14 |
* case, route_call() will perform the wakeup. |
*/ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* |
* Futex is up after getting back from async_manager get it |
* again. |
* Futex is up after getting back from async_manager. |
* Get it again. |
*/ |
futex_down(&async_futex); |
if (usecs && conn->wdata.timedout && |
list_empty(&conn->msg_queue)) { |
if ((usecs) && (conn->wdata.timedout) |
&& (list_empty(&conn->msg_queue))) { |
/* If we timed out -> exit */ |
futex_up(&async_futex); |
return 0; |
388,9 → 436,10 |
} |
} |
msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
list_remove(&msg->link); |
callid = msg->callid; |
ipc_callid_t callid = msg->callid; |
*call = msg->call; |
free(msg); |
404,6 → 453,7 |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
{ |
412,8 → 462,11 |
/** Default fibril function that gets called to handle interrupt notifications. |
* |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
427,14 → 480,14 |
* @param arg Connection structure pointer. |
* |
* @return Always zero. |
* |
*/ |
static int connection_fibril(void *arg) |
{ |
unsigned long key; |
msg_t *msg; |
int close_answered = 0; |
/* Setup fibril-local connection pointer */ |
/* |
* Setup fibril-local connection pointer and call client_connection(). |
* |
*/ |
FIBRIL_connection = (connection_t *) arg; |
FIBRIL_connection->cfibril(FIBRIL_connection->callid, |
&FIBRIL_connection->call); |
441,20 → 494,20 |
/* Remove myself from the connection hash table */ |
futex_down(&async_futex); |
key = FIBRIL_connection->in_phone_hash; |
unsigned long key = FIBRIL_connection->in_phone_hash; |
hash_table_remove(&conn_hash_table, &key, 1); |
futex_up(&async_futex); |
/* Answer all remaining messages with EHANGUP */ |
while (!list_empty(&FIBRIL_connection->msg_queue)) { |
msg = list_get_instance(FIBRIL_connection->msg_queue.next, |
msg_t, link); |
msg_t *msg |
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link); |
list_remove(&msg->link); |
if (msg->callid == FIBRIL_connection->close_callid) |
close_answered = 1; |
ipc_answer_0(msg->callid, EHANGUP); |
free(msg); |
} |
if (FIBRIL_connection->close_callid) |
ipc_answer_0(FIBRIL_connection->close_callid, EOK); |
463,7 → 516,7 |
/** Create a new fibril for a new connection. |
* |
* Creates new fibril for connection, fills in connection structures and inserts |
* Create new fibril for connection, fill in connection structures and inserts |
* it into the hash table, so that later we can easily do routing of messages to |
* particular fibrils. |
* |
477,29 → 530,31 |
* connection. |
* |
* @return New fibril id or NULL on failure. |
* |
*/ |
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) |
{ |
connection_t *conn; |
unsigned long key; |
conn = malloc(sizeof(*conn)); |
connection_t *conn = malloc(sizeof(*conn)); |
if (!conn) { |
if (callid) |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
conn->in_phone_hash = in_phone_hash; |
list_initialize(&conn->msg_queue); |
conn->callid = callid; |
conn->close_callid = 0; |
conn->close_callid = false; |
if (call) |
conn->call = *call; |
conn->wdata.active = 1; /* We will activate the fibril ASAP */ |
/* We will activate the fibril ASAP */ |
conn->wdata.active = true; |
conn->cfibril = cfibril; |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
if (callid) |
508,7 → 563,8 |
} |
/* Add connection to the connection hash table */ |
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); |
futex_up(&async_futex); |
531,9 → 587,7 |
{ |
/* Unrouted call - do some default behaviour */ |
if ((callid & IPC_CALLID_NOTIFICATION)) { |
_in_interrupt_handler = 1; |
(*interrupt_received)(callid, call); |
_in_interrupt_handler = 0; |
process_notification(callid, call); |
return; |
} |
557,27 → 611,29 |
static void handle_expired_timeouts(void) |
{ |
struct timeval tv; |
awaiter_t *waiter; |
link_t *cur; |
gettimeofday(&tv, NULL); |
gettimeofday(&tv, NULL); |
futex_down(&async_futex); |
cur = timeout_list.next; |
link_t *cur = timeout_list.next; |
while (cur != &timeout_list) { |
waiter = list_get_instance(cur, awaiter_t, link); |
awaiter_t *waiter = list_get_instance(cur, awaiter_t, link); |
if (tv_gt(&waiter->expires, &tv)) |
break; |
cur = cur->next; |
list_remove(&waiter->link); |
waiter->inlist = 0; |
waiter->timedout = 1; |
waiter->inlist = false; |
waiter->timedout = true; |
/* |
* Redundant condition? |
* The fibril should not be active when it gets here. |
*/ |
if (!waiter->active) { |
waiter->active = 1; |
waiter->active = true; |
fibril_add_ready(waiter->fid); |
} |
} |
588,16 → 644,11 |
/** Endless loop dispatching incoming calls and answers. |
* |
* @return Never returns. |
* |
*/ |
static int async_manager_worker(void) |
{ |
ipc_call_t call; |
ipc_callid_t callid; |
int timeout; |
awaiter_t *waiter; |
struct timeval tv; |
while (1) { |
while (true) { |
if (fibril_switch(FIBRIL_FROM_MANAGER)) { |
futex_up(&async_futex); |
/* |
606,11 → 657,17 |
*/ |
continue; |
} |
futex_down(&async_futex); |
suseconds_t timeout; |
if (!list_empty(&timeout_list)) { |
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); |
if (tv_gteq(&tv, &waiter->expires)) { |
futex_up(&async_futex); |
handle_expired_timeouts(); |
619,9 → 676,12 |
timeout = tv_sub(&waiter->expires, &tv); |
} else |
timeout = SYNCH_NO_TIMEOUT; |
futex_up(&async_futex); |
callid = ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
ipc_call_t call; |
ipc_callid_t callid |
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
if (!callid) { |
handle_expired_timeouts(); |
628,9 → 688,8 |
continue; |
} |
if (callid & IPC_CALLID_ANSWERED) { |
if (callid & IPC_CALLID_ANSWERED) |
continue; |
} |
handle_call(callid, &call); |
} |
643,12 → 702,13 |
* When more kernel threads are used, one async manager should exist per thread. |
* |
* @param arg Unused. |
* @return Never returns. |
* |
* @return Never returns. |
*/ |
static int async_manager_fibril(void *arg) |
{ |
futex_up(&async_futex); |
/* |
* async_futex is always locked when entering manager |
*/ |
660,9 → 720,7 |
/** Add one manager to manager list. */ |
void async_create_manager(void) |
{ |
fid_t fid; |
fid = fibril_create(async_manager_fibril, NULL); |
fid_t fid = fibril_create(async_manager_fibril, NULL); |
fibril_add_manager(fid); |
} |
694,30 → 752,33 |
* |
* Notify the fibril which is waiting for this message that it has arrived. |
* |
* @param private Pointer to the asynchronous message record. |
* @param arg Pointer to the asynchronous message record. |
* @param retval Value returned in the answer. |
* @param data Call data of the answer. |
*/ |
static void reply_received(void *private, int retval, ipc_call_t *data) |
static void reply_received(void *arg, int retval, ipc_call_t *data) |
{ |
amsg_t *msg = (amsg_t *) private; |
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) |
*msg->dataptr = *data; |
write_barrier(); |
/* Remove message from timeout list */ |
if (msg->wdata.inlist) |
list_remove(&msg->wdata.link); |
msg->done = 1; |
msg->done = true; |
if (!msg->wdata.active) { |
msg->wdata.active = 1; |
msg->wdata.active = true; |
fibril_add_ready(msg->wdata.fid); |
} |
futex_up(&async_futex); |
} |
735,22 → 796,25 |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
/* We may sleep in the next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
reply_received, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
770,23 → 834,26 |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
/* We may sleep in next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
reply_received, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
796,6 → 863,7 |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* |
*/ |
void async_wait_for(aid_t amsgid, ipcarg_t *retval) |
{ |
808,14 → 876,18 |
} |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.inlist = 0; |
msg->wdata.active = false; |
msg->wdata.inlist = false; |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
} |
827,6 → 899,7 |
* @param timeout Timeout in microseconds. |
* |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* |
*/ |
int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout) |
{ |
846,13 → 919,14 |
tv_add(&msg->wdata.expires, timeout); |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
if (!msg->done) |
return ETIMEOUT; |
859,6 → 933,7 |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
return 0; |
869,26 → 944,30 |
* The current fibril is suspended but the thread continues to execute. |
* |
* @param timeout Duration of the wait in microseconds. |
* |
*/ |
void async_usleep(suseconds_t timeout) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
if (!msg) |
return; |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
futex_down(&async_futex); |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch()...*/ |
/* Futex is up automatically after fibril_switch() */ |
free(msg); |
} |
895,6 → 974,7 |
/** Setter for client_connection function pointer. |
* |
* @param conn Function that will implement a new connection fibril. |
* |
*/ |
void async_set_client_connection(async_client_conn_t conn) |
{ |
903,12 → 983,12 |
/** Setter for interrupt_received function pointer. |
* |
* @param conn Function that will implement a new interrupt |
* @param intr Function that will implement a new interrupt |
* notification fibril. |
*/ |
void async_set_interrupt_received(async_client_conn_t conn) |
void async_set_interrupt_received(async_client_conn_t intr) |
{ |
interrupt_received = conn; |
interrupt_received = intr; |
} |
/** Pseudo-synchronous message sending - fast version. |
929,7 → 1009,9 |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2, |
936,21 → 1018,27 |
ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
970,7 → 1058,9 |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1, |
977,21 → 1067,27 |
ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
/branches/network/uspace/lib/libc/generic/vfs/vfs.c |
---|
76,7 → 76,7 |
futex_up(&cwd_futex); |
return NULL; |
} |
str_ncpy(ncwd_path_nc, cwd_path, cwd_size + 1 + size + 1); |
str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path); |
ncwd_path_nc[cwd_size] = '/'; |
ncwd_path_nc[cwd_size + 1] = '\0'; |
} else { |
87,7 → 87,7 |
} |
ncwd_path_nc[0] = '\0'; |
} |
strcat(ncwd_path_nc, path); |
str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path); |
ncwd_path = canonify(ncwd_path_nc, retlen); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
99,7 → 99,7 |
* the address in ncwd_path need not be the same as ncwd_path_nc, even |
* though they both point into the same dynamically allocated buffer. |
*/ |
ncwd_path = strdup(ncwd_path); |
ncwd_path = str_dup(ncwd_path); |
free(ncwd_path_nc); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
155,7 → 155,7 |
} |
int mount(const char *fs_name, const char *mp, const char *dev, |
const unsigned int flags) |
const char *opts, const unsigned int flags) |
{ |
int res; |
ipcarg_t rc; |
185,6 → 185,15 |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
194,6 → 203,16 |
return (int) rc; |
} |
/* Ask VFS whether it likes fs_name. */ |
rc = async_req_0_0(vfs_phone, IPC_M_PING); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
534,7 → 553,7 |
futex_up(&cwd_futex); |
return NULL; |
} |
str_ncpy(buf, cwd_path, size); |
str_cpy(buf, size, cwd_path); |
futex_up(&cwd_futex); |
return buf; |
} |
/branches/network/uspace/lib/libc/generic/io/io.c |
---|
38,6 → 38,7 |
#include <io/io.h> |
#include <string.h> |
#include <errno.h> |
#include <console.h> |
const static char nl = '\n'; |
49,8 → 50,9 |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) { |
if (write_stdout(&nl, 1) == 1) |
if (console_write((void *) str, count) == count) { |
if (console_write(&nl, 1) == 1) |
return 0; |
} |
64,7 → 66,7 |
*/ |
int putnchars(const char *buf, size_t count) |
{ |
if (write_stdout((void *) buf, count) == count) |
if (console_write((void *) buf, count) == count) |
return 0; |
return EOF; |
81,7 → 83,7 |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) |
if (console_write((void *) str, count) == count) |
return 0; |
return EOF; |
96,7 → 98,7 |
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK) |
return EOF; |
if (write_stdout((void *) buf, offs) == offs) |
if (console_write((void *) buf, offs) == offs) |
return c; |
return EOF; |
106,7 → 108,7 |
{ |
unsigned char c; |
flush_stdout(); |
console_flush(); |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
115,8 → 117,10 |
int fflush(FILE *f) |
{ |
/* Dummy implementation */ |
(void) f; |
return flush_stdout(); |
console_flush(); |
return 0; |
} |
/** @} |
/branches/network/uspace/lib/libc/generic/io/vprintf.c |
---|
38,6 → 38,7 |
#include <io/printf_core.h> |
#include <futex.h> |
#include <async.h> |
#include <console.h> |
static atomic_t printf_futex = FUTEX_INITIALIZER; |
50,7 → 51,7 |
while (offset < size) { |
prev = offset; |
str_decode(str, &offset, size); |
write_stdout(str + prev, offset - prev); |
console_write(str + prev, offset - prev); |
chars++; |
} |
67,7 → 68,7 |
while (offset < size) { |
boff = 0; |
chr_encode(str[chars], buf, &boff, 4); |
write_stdout(buf, boff); |
console_write(buf, boff); |
chars++; |
offset += sizeof(wchar_t); |
} |
/branches/network/uspace/lib/libc/generic/io/stream.c |
---|
49,14 → 49,9 |
#include <async.h> |
#include <sys/types.h> |
ssize_t write_stderr(const void *buf, size_t count) |
{ |
return count; |
} |
ssize_t read_stdin(void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int cons_phone = console_open(false); |
if (cons_phone >= 0) { |
kbd_event_t ev; |
72,39 → 67,10 |
((char *) buf)[i++] = ev.c; |
} |
return i; |
} else { |
} else |
return -1; |
} |
} |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int left, rc; |
if (cons_phone >= 0) { |
int i; |
left = count; |
while (left > 0) { |
rc = console_write(buf, left); |
if (rc < 0) |
break; |
buf += rc; |
left -= rc; |
} |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
int flush_stdout(void) |
{ |
console_flush(); |
return 0; |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
/branches/network/uspace/lib/libc/arch/ia64/include/ddi.h |
---|
53,7 → 53,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
63,7 → 63,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
73,7 → 73,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
85,7 → 85,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
95,7 → 95,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
105,7 → 105,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
/branches/network/uspace/srv/kbd/include/layout.h |
---|
41,6 → 41,7 |
#include <sys/types.h> |
typedef struct { |
void (*reset)(void); |
wchar_t (*parse_ev)(kbd_event_t *); |
} layout_op_t; |
/branches/network/uspace/srv/kbd/include/sun.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Sun keyboard virtual port driver. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_SUN_H_ |
#define KBD_SUN_H_ |
extern int ns16550_port_init(void); |
extern int z8530_port_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/network/uspace/srv/kbd/port/ns16550.c |
---|
35,10 → 35,12 |
*/ |
#include <ipc/ipc.h> |
#include <ipc/bus.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <ddi.h> |
/* NS16550 registers */ |
89,7 → 91,7 |
static uintptr_t ns16550_physical; |
static uintptr_t ns16550_kernel; |
int kbd_port_init(void) |
int ns16550_port_init(void) |
{ |
void *vaddr; |
100,7 → 102,7 |
ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG); |
ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG); |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), |
0, &ns16550_kbd); |
sysinfo_value("kbd.inr"), &ns16550_kbd); |
return pio_enable((void *) ns16550_physical, 8, &vaddr); |
} |
108,6 → 110,10 |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
if (cir_service) |
async_msg_1(cir_phone, BUS_CLEAR_INTERRUPT, |
IPC_GET_METHOD(*call)); |
} |
/** |
/branches/network/uspace/srv/kbd/port/sun.c |
---|
0,0 → 1,66 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Sun keyboard virtual port driver. |
*/ |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <sysinfo.h> |
/** Sun keyboard virtual port driver. |
* |
* This is a virtual port driver which can use |
* both ns16550_port_init and z8530_port_init |
* according to the information passed from the |
* kernel. This is just a temporal hack. |
* |
*/ |
int kbd_port_init(void) |
{ |
if (sysinfo_value("kbd.type.z8530")) { |
if (z8530_port_init() == 0) |
return 0; |
} |
if (sysinfo_value("kbd.type.ns16550")) { |
if (ns16550_port_init() == 0) |
return 0; |
} |
return -1; |
} |
/** @} |
*/ |
/branches/network/uspace/srv/kbd/port/z8530.c |
---|
40,6 → 40,7 |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <sys/types.h> |
#include <ddi.h> |
82,7 → 83,7 |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
int z8530_port_init(void) |
{ |
async_set_interrupt_received(z8530_irq_handler); |
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") + |
/branches/network/uspace/srv/kbd/generic/kbd.c |
---|
136,6 → 136,7 |
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F1) { |
active_layout = 0; |
layout[active_layout]->reset(); |
return; |
} |
142,6 → 143,7 |
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F2) { |
active_layout = 1; |
layout[active_layout]->reset(); |
return; |
} |
148,6 → 150,7 |
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F3) { |
active_layout = 2; |
layout[active_layout]->reset(); |
return; |
} |
224,6 → 227,9 |
if (kbd_ctl_init() != 0) |
return -1; |
/* Initialize (reset) layout. */ |
layout[active_layout]->reset(); |
/* Initialize key buffer */ |
keybuffer_init(&keybuffer); |
/branches/network/uspace/srv/kbd/Makefile |
---|
59,9 → 59,11 |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(UARCH), arm32) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
70,29 → 72,35 |
ctl/stty.c |
endif |
endif |
ifeq ($(UARCH), ia32) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(MACHINE), i460GX) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(MACHINE), ski) |
GENARCH_SOURCES += \ |
port/ski.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), msim) |
GENARCH_SOURCES += \ |
port/msim.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), lgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
101,16 → 109,19 |
ctl/stty.c |
endif |
endif |
ifeq ($(MACHINE), bgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c \ |
ctl/stty.c |
endif |
ifeq ($(UARCH), ppc32) |
GENARCH_SOURCES += \ |
port/dummy.c \ |
ctl/stty.c |
endif |
ifeq ($(UARCH), sparc64) |
ifeq ($(MACHINE),serengeti) |
GENARCH_SOURCES += \ |
118,7 → 129,9 |
ctl/stty.c |
else |
GENARCH_SOURCES += \ |
port/sun.c \ |
port/z8530.c \ |
port/ns16550.c \ |
ctl/sun.c |
endif |
endif |
/branches/network/uspace/srv/kbd/layout/us_qwerty.c |
---|
36,9 → 36,11 |
#include <kbd/keycode.h> |
#include <layout.h> |
static void layout_reset(void); |
static wchar_t layout_parse_ev(kbd_event_t *ev); |
layout_op_t us_qwerty_op = { |
layout_reset, |
layout_parse_ev |
}; |
197,6 → 199,10 |
return map[key]; |
} |
static void layout_reset(void) |
{ |
} |
static wchar_t layout_parse_ev(kbd_event_t *ev) |
{ |
wchar_t c; |
/branches/network/uspace/srv/kbd/layout/cz.c |
---|
34,28 → 34,26 |
#include <kbd.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(kbd_event_t *ev); |
enum m_state { |
ms_start, |
ms_hacek, |
ms_carka |
}; |
static enum m_state mstate; |
layout_op_t cz_op = { |
layout_reset, |
layout_parse_ev |
}; |
static wchar_t map_lcase[] = { |
[KC_2] = L'ě', |
[KC_3] = L'š', |
[KC_4] = L'č', |
[KC_5] = L'ř', |
[KC_6] = L'ž', |
[KC_7] = L'ý', |
[KC_8] = L'á', |
[KC_9] = L'í', |
[KC_0] = L'é', |
[KC_LBRACKET] = L'ú', |
[KC_SEMICOLON] = L'ů', |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
87,19 → 85,6 |
}; |
static wchar_t map_ucase[] = { |
[KC_2] = L'Ě', |
[KC_3] = L'Š', |
[KC_4] = L'Č', |
[KC_5] = L'Ř', |
[KC_6] = L'Ž', |
[KC_7] = L'Ý', |
[KC_8] = L'Á', |
[KC_9] = L'Í', |
[KC_0] = L'É', |
[KC_LBRACKET] = L'Ú', |
[KC_SEMICOLON] = L'Ů', |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
172,6 → 157,36 |
[KC_SLASH] = '_', |
}; |
static wchar_t map_ns_nocaps[] = { |
[KC_2] = L'ě', |
[KC_3] = L'š', |
[KC_4] = L'č', |
[KC_5] = L'ř', |
[KC_6] = L'ž', |
[KC_7] = L'ý', |
[KC_8] = L'á', |
[KC_9] = L'í', |
[KC_0] = L'é', |
[KC_LBRACKET] = L'ú', |
[KC_SEMICOLON] = L'ů' |
}; |
static wchar_t map_ns_caps[] = { |
[KC_2] = L'Ě', |
[KC_3] = L'Š', |
[KC_4] = L'Č', |
[KC_5] = L'Ř', |
[KC_6] = L'Ž', |
[KC_7] = L'Ý', |
[KC_8] = L'Á', |
[KC_9] = L'Í', |
[KC_0] = L'É', |
[KC_LBRACKET] = L'Ú', |
[KC_SEMICOLON] = L'Ů' |
}; |
static wchar_t map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
200,6 → 215,56 |
[KC_NPERIOD] = '.' |
}; |
static wchar_t map_hacek_lcase[] = { |
[KC_E] = L'ě', |
[KC_R] = L'ř', |
[KC_T] = L'ť', |
[KC_Y] = L'ž', |
[KC_U] = L'ů', |
[KC_S] = L'š', |
[KC_D] = L'ď', |
[KC_C] = L'č', |
[KC_N] = L'ň' |
}; |
static wchar_t map_hacek_ucase[] = { |
[KC_E] = L'Ě', |
[KC_R] = L'Ř', |
[KC_T] = L'Ť', |
[KC_Y] = L'Ž', |
[KC_U] = L'Ů', |
[KC_S] = L'Š', |
[KC_D] = L'Ď', |
[KC_C] = L'Č', |
[KC_N] = L'Ň' |
}; |
static wchar_t map_carka_lcase[] = { |
[KC_E] = L'é', |
[KC_U] = L'ú', |
[KC_I] = L'í', |
[KC_O] = L'ó', |
[KC_A] = L'á', |
[KC_Z] = L'ý', |
}; |
static wchar_t map_carka_ucase[] = { |
[KC_E] = L'É', |
[KC_U] = L'Ú', |
[KC_I] = L'Í', |
[KC_O] = L'Ó', |
[KC_A] = L'Á', |
[KC_Z] = L'Ý', |
}; |
static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length) |
{ |
if (key >= map_length) |
207,18 → 272,73 |
return map[key]; |
} |
static wchar_t layout_parse_ev(kbd_event_t *ev) |
static wchar_t parse_ms_hacek(kbd_event_t *ev) |
{ |
wchar_t c; |
mstate = ms_start; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t)); |
return c; |
} |
static wchar_t parse_ms_carka(kbd_event_t *ev) |
{ |
wchar_t c; |
mstate = ms_start; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t)); |
return c; |
} |
static wchar_t parse_ms_start(kbd_event_t *ev) |
{ |
wchar_t c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (ev->key == KC_EQUALS) { |
if ((ev->mods & KM_SHIFT) != 0) |
mstate = ms_hacek; |
else |
mstate = ms_carka; |
return 0; |
} |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) == 0) { |
if ((ev->mods & KM_CAPS_LOCK) != 0) |
c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
} |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t)); |
else |
243,6 → 363,41 |
return c; |
} |
static bool key_is_mod(unsigned key) |
{ |
switch (key) { |
case KC_LSHIFT: |
case KC_RSHIFT: |
case KC_LALT: |
case KC_RALT: |
case KC_LCTRL: |
case KC_RCTRL: |
return true; |
default: |
return false; |
} |
} |
static void layout_reset(void) |
{ |
mstate = ms_start; |
} |
static wchar_t layout_parse_ev(kbd_event_t *ev) |
{ |
if (ev->type != KE_PRESS) |
return '\0'; |
if (key_is_mod(ev->key)) |
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); |
} |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/kbd/layout/us_dvorak.c |
---|
36,9 → 36,11 |
#include <kbd/keycode.h> |
#include <layout.h> |
static void layout_reset(void); |
static wchar_t layout_parse_ev(kbd_event_t *ev); |
layout_op_t us_dvorak_op = { |
layout_reset, |
layout_parse_ev |
}; |
203,6 → 205,10 |
return map[key]; |
} |
static void layout_reset(void) |
{ |
} |
static wchar_t layout_parse_ev(kbd_event_t *ev) |
{ |
wchar_t c; |
/branches/network/uspace/srv/console/console.c |
---|
141,6 → 141,16 |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
} |
static void screen_yield(void) |
{ |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD); |
} |
static void screen_reclaim(void) |
{ |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM); |
} |
static void set_style(int style) |
{ |
async_msg_1(fb_info.phone, FB_SET_STYLE, style); |
330,8 → 340,10 |
async_serialize_start(); |
curs_hide_sync(); |
gcons_in_kernel(); |
screen_yield(); |
async_serialize_end(); |
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { |
prev_console = active_console; |
active_console = KERNEL_CONSOLE; |
342,8 → 354,10 |
if (newcons != KERNEL_CONSOLE) { |
async_serialize_start(); |
if (active_console == KERNEL_CONSOLE) |
if (active_console == KERNEL_CONSOLE) { |
screen_reclaim(); |
gcons_redraw_console(); |
} |
active_console = newcons; |
gcons_change_console(newcons); |
512,6 → 526,8 |
gcons_notify_connect(consnum); |
conn->client_phone = IPC_GET_ARG5(*icall); |
screenbuffer_clear(&conn->screenbuffer); |
if (consnum == active_console) |
clrscr(); |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
/branches/network/uspace/srv/rd/rd.c |
---|
196,7 → 196,7 |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *) name, strlen(name) + 1); |
retval = ipc_data_write_start(phone, (char *) name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
219,7 → 219,8 |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *) name, strlen(name) + 1); |
retval = ipc_data_write_start(driver_phone, (char *) name, |
str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
/branches/network/uspace/srv/loader/main.c |
---|
150,11 → 150,11 |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_len, arg_len; |
size_t buf_size, arg_size; |
char *p; |
int n; |
if (!ipc_data_write_receive(&callid, &buf_len)) { |
if (!ipc_data_write_receive(&callid, &buf_size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
170,7 → 170,7 |
argv = NULL; |
} |
arg_buf = malloc(buf_len + 1); |
arg_buf = malloc(buf_size + 1); |
if (!arg_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
177,9 → 177,9 |
return; |
} |
ipc_data_write_finalize(callid, arg_buf, buf_len); |
ipc_data_write_finalize(callid, arg_buf, buf_size); |
arg_buf[buf_len] = '\0'; |
arg_buf[buf_size] = '\0'; |
/* |
* Count number of arguments |
186,9 → 186,9 |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
p = p + arg_len + 1; |
while (p < arg_buf + buf_size) { |
arg_size = str_size(p); |
p = p + arg_size + 1; |
++n; |
} |
206,11 → 206,11 |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
while (p < arg_buf + buf_size) { |
argv[n] = p; |
arg_len = strlen(p); |
p = p + arg_len + 1; |
arg_size = str_size(p); |
p = p + arg_size + 1; |
++n; |
} |
275,7 → 275,7 |
const char *cp; |
/* Set the task name. */ |
cp = strrchr(pathname, '/'); |
cp = str_rchr(pathname, '/'); |
cp = (cp == NULL) ? pathname : (cp + 1); |
task_set_name(cp); |
/branches/network/uspace/srv/net/net/net_standalone.c |
---|
34,7 → 34,7 |
* |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <ipc/ipc.h> |
91,7 → 91,7 |
int read_netif_configuration( char * name, netif_ref netif ){ |
ERROR_DECLARE; |
if( strncmp( name, "lo", 2 ) == 0 ){ |
if( str_lcmp( name, "lo", 2 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
98,7 → 98,7 |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" )); |
}else if( strncmp( name, "ne2k", 4 ) == 0 ){ |
}else if( str_lcmp( name, "ne2k", 4 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME )); |
// standalone ethernet |
/branches/network/uspace/srv/net/net/net_bundle.c |
---|
123,7 → 123,7 |
int read_netif_configuration( char * name, netif_ref netif ){ |
ERROR_DECLARE; |
if( strncmp( name, "lo", 2 ) == 0 ){ |
if( str_lcmp( name, "lo", 2 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
130,7 → 130,7 |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" )); |
}else if( strncmp( name, "ne2k", 4 ) == 0 ){ |
}else if( str_lcmp( name, "ne2k", 4 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME )); |
// ethernet bundled in dp8390 |
/branches/network/uspace/srv/net/il/arp/arp.c |
---|
40,6 → 40,7 |
#include <mem.h> |
#include <rwlock.h> |
#include <stdio.h> |
#include <string.h> |
#include <task.h> |
#include <ipc/ipc.h> |
434,7 → 435,7 |
if( proto->addr->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )){ |
return EINVAL; |
} |
if( ! strncmp( proto->addr->value, ( char * ) des_proto, proto->addr->length )){ |
if( ! str_lcmp( proto->addr->value, ( char * ) des_proto, proto->addr->length )){ |
// not already upadted? |
if( ! hw_source ){ |
hw_source = measured_string_create_bulk(( char * ) src_hw, CONVERT_SIZE( uint8_t, char, header->hardware_length )); |
/branches/network/uspace/srv/net/il/ip/ip.c |
---|
36,6 → 36,7 |
#include <async.h> |
#include <errno.h> |
#include <stdio.h> |
#include <string.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
112,7 → 113,7 |
}else{ |
ip_netif->ipv = DEFAULT_IPV; |
} |
ip_netif->dhcp = ! strncmp( configuration[ 1 ].value, "dhcp", 4 ); |
ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", 4 ); |
if( ip_netif->dhcp ){ |
// TODO dhcp |
net_free_settings( configuration, data ); |
254,7 → 255,10 |
if( netif->arp ){ |
address.value = ( char * ) & netif->gateway; |
address.length = CONVERT_SIZE( in_addr_t, char, 1 ); |
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
sleep( 2 ); |
ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
} |
printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
free( translation ); |
free( data ); |
/branches/network/uspace/srv/net/netif/dp8390/dp8390.c |
---|
205,6 → 205,58 |
} |
/*===========================================================================* |
* dp8390_dump * |
*===========================================================================*/ |
void dp8390_dump( dpeth_t * dep ) |
{ |
// dpeth_t *dep; |
int /*i,*/ isr; |
// printf("\n"); |
// for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++) |
// { |
#if XXX |
if (dep->de_mode == DEM_DISABLED) |
printf("dp8390 port %d is disabled\n", i); |
else if (dep->de_mode == DEM_SINK) |
printf("dp8390 port %d is in sink mode\n", i); |
#endif |
if (dep->de_mode != DEM_ENABLED) |
// continue; |
return; |
// printf("dp8390 statistics of port %d:\n", i); |
printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr); |
printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr); |
printf("OVW :%8ld\n", dep->de_stat.ets_OVW); |
printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr); |
printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll); |
printf("missedP :%8ld\n", dep->de_stat.ets_missedP); |
printf("packetR :%8ld\t", dep->de_stat.ets_packetR); |
printf("packetT :%8ld\t", dep->de_stat.ets_packetT); |
printf("transDef :%8ld\n", dep->de_stat.ets_transDef); |
printf("collision :%8ld\t", dep->de_stat.ets_collision); |
printf("transAb :%8ld\t", dep->de_stat.ets_transAb); |
printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense); |
printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder); |
printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver); |
printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat); |
printf("OWC :%8ld\t", dep->de_stat.ets_OWC); |
isr= inb_reg0(dep, DP_ISR); |
printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr, |
inb_reg0(dep, DP_ISR), dep->de_flags); |
// } |
} |
/*===========================================================================* |
* do_init * |
*===========================================================================*/ |
int do_init( dpeth_t * dep, int mode ){ |
588,10 → 640,11 |
/*===========================================================================* |
* dp_check_ints * |
*===========================================================================*/ |
void dp_check_ints(dep) |
void dp_check_ints(dep, isr) |
dpeth_t *dep; |
int isr; |
{ |
int isr, tsr; |
int /*isr,*/ tsr; |
int size, sendq_tail; |
if (!(dep->de_flags & DEF_ENABLED)) |
599,7 → 652,7 |
for(;;) |
{ |
isr = inb_reg0(dep, DP_ISR); |
// isr = inb_reg0(dep, DP_ISR); |
if (!isr) |
break; |
outb_reg0(dep, DP_ISR, isr); |
720,6 → 773,7 |
dep->de_flags |= DEF_STOPPED; |
break; |
} |
isr = inb_reg0(dep, DP_ISR); |
} |
if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == |
(DEF_READING|DEF_STOPPED)) |
1504,8 → 1558,8 |
if (r < 0) |
panic("", "dp8390: send failed:", r); |
dep->de_read_s = 0; |
*/ dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV); |
*/ dep->de_read_s = 0; |
dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV); |
} |
/*===========================================================================* |
/branches/network/uspace/srv/net/netif/dp8390/dp8390_drv.h |
---|
40,9 → 40,10 |
_PROTOTYPE( int do_init, (dpeth_t *dep, int mode) ); |
_PROTOTYPE( void do_stop, (dpeth_t *dep) ); |
_PROTOTYPE( void dp_check_ints, (dpeth_t *dep) ); |
_PROTOTYPE( void dp_check_ints, (dpeth_t *dep, int isr) ); |
int do_probe( dpeth_t * dep ); |
int do_pwrite( dpeth_t * dep, packet_t packet, int from_int ); |
void dp8390_dump( dpeth_t * dep ); |
#endif |
/branches/network/uspace/srv/net/netif/dp8390/dp8390_module.c |
---|
34,6 → 34,7 |
*/ |
#include <assert.h> |
#include <async.h> |
#include <ddi.h> |
#include <errno.h> |
#include <malloc.h> |
70,14 → 71,14 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.value = 1, |
.srcarg = 2 |
}, |
{ .cmd = CMD_PIO_WRITE_8, |
/* { .cmd = CMD_PIO_WRITE_8, |
.addr = NULL, |
.srcarg = 2 |
.value = 0 |
}, |
{ |
*/ { |
.cmd = CMD_ACCEPT |
} |
}; |
141,7 → 142,6 |
void irq_handler( ipc_callid_t iid, ipc_call_t * call ) |
{ |
// int irq; |
device_ref device; |
dpeth_t * dep; |
packet_t received; |
148,35 → 148,31 |
device_id_t device_id; |
int phone; |
// async_serialize_start(); |
device_id = IRQ_GET_DEVICE( call ); |
// printf( "device %d - irq %x\n", device_id, IPC_GET_ISR( call )); |
rwlock_write_lock( & netif_globals.lock ); |
if( find_device( device_id, & device ) != EOK ){ |
rwlock_write_unlock( & netif_globals.lock ); |
// async_serialize_end() |
return; |
} |
dep = ( dpeth_t * ) device->specific; |
// printf( "dev %d, irq %x\n\n", device->device_id, IPC_GET_ISR( call )); |
if ( dep->de_mode != DEM_ENABLED){ |
// continue; |
rwlock_write_unlock( & netif_globals.lock ); |
// async_serialize_end() |
return; |
} |
assert( dep->de_flags & DEF_ENABLED); |
// irq= dep.de_irq; |
// assert(irq >= 0 && irq < NR_IRQ_VECTORS); |
// if ( dep->de_int_pending || 1) |
// { |
dep->de_int_pending= 0; |
dp_check_ints( dep ); |
// do_int(dep); |
/* r= sys_irqenable(&dep->de_hook); |
if (r != OK) |
{ |
panic("DP8390", |
"unable enable interrupts", r); |
} |
*/// } |
printf( "I%d -%d\n", device_id, IPC_GET_ISR( call )); |
/* putchar( 'I' ); |
putchar( '0' + device_id ); |
putchar( '-' ); |
putchar( '0' + IPC_GET_ISR( call ) / 100 ); |
putchar( '0' + ( IPC_GET_ISR( call ) % 100 ) / 10 ); |
putchar( '0' + IPC_GET_ISR( call ) % 10 ); |
putchar( '\n' ); |
*/ dp_check_ints( dep, IPC_GET_ISR( call )); |
if( dep->received_queue ){ |
received = dep->received_queue; |
phone = device->nil_phone; |
187,6 → 183,7 |
rwlock_write_unlock( & netif_globals.lock ); |
} |
ipc_answer_0( iid, EOK ); |
// async_serialize_end() |
} |
int netif_probe_auto_message( void ){ |
236,12 → 233,13 |
dpeth_t * dep; |
packet_t next; |
ERROR_PROPAGATE( find_device( device_id, & device )); |
dep = ( dpeth_t * ) device->specific; |
// TODO remove debug dump: |
uint8_t * data; |
data = packet_get_data( packet ); |
printf( "Sending packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ], data[ 16 ], data[ 17 ], data[ 18 ], data[ 19 ], data[ 20 ], data[ 21 ], data[ 22 ], data[ 23 ], data[ 24 ], data[ 25 ], data[ 26 ], data[ 27 ], data[ 28 ], data[ 29 ], data[ 30 ], data[ 31 ], data[ 32 ], data[ 33 ], data[ 34 ], data[ 35 ], data[ 36 ], data[ 37 ], data[ 38 ], data[ 39 ], data[ 40 ], data[ 41 ], data[ 42 ], data[ 43 ], data[ 44 ], data[ 45 ], data[ 46 ], data[ 47 ], data[ 48 ], data[ 49 ], data[ 50 ], data[ 51 ], data[ 52 ], data[ 53 ], data[ 54 ], data[ 55 ], data[ 56 ], data[ 57 ], data[ 58 ], data[ 59 ] ); |
ERROR_PROPAGATE( find_device( device_id, & device )); |
dep = ( dpeth_t * ) device->specific; |
// process packet queue |
do{ |
next = pq_detach( packet ); |
250,6 → 248,7 |
} |
packet = next; |
}while( packet ); |
dp8390_dump( dep ); |
return EOK; |
} |
/branches/network/uspace/srv/fb/serial_console.c |
---|
274,9 → 274,6 |
serial_goto(y, x); |
for (i = 0; i < w; i++) { |
unsigned int col = x + i; |
unsigned int row = y + j; |
field = &data[j * w + i]; |
a1 = &field->attrs; |
304,12 → 301,9 |
wchar_t c; |
int col, row, w, h; |
int fgcolor; |
int bgcolor; |
int flags; |
int style; |
int i; |
attrs_t cur_attr; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
319,6 → 313,9 |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
cur_attr.t = at_style; |
cur_attr.a.s.style = STYLE_NORMAL; |
/* Clear the terminal, set scrolling region |
to 0 - height rows. */ |
serial_clrscr(); |
388,23 → 385,28 |
retval = 0; |
break; |
case FB_SET_STYLE: |
style = IPC_GET_ARG1(call); |
serial_set_style(style); |
cur_attr.t = at_style; |
cur_attr.a.s.style = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
case FB_SET_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
flags = IPC_GET_ARG3(call); |
cur_attr.t = at_idx; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
cur_attr.a.i.flags = IPC_GET_ARG3(call); |
serial_set_attrs(&cur_attr); |
serial_set_idx(fgcolor, bgcolor, flags); |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
cur_attr.t = at_rgb; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
serial_set_rgb(fgcolor, bgcolor); |
retval = 0; |
break; |
case FB_SCROLL: |
424,6 → 426,18 |
serial_cursor_disable(); |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
serial_sgr(SGR_RESET); |
serial_puts("\033[2J"); |
serial_goto(0, 0); |
serial_cursor_enable(); |
retval = 0; |
break; |
case FB_SCREEN_RECLAIM: |
serial_clrscr(); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
/branches/network/uspace/srv/fb/fb.c |
---|
78,6 → 78,9 |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
/** Function to render a bit mask. */ |
typedef void (*mask_conv_t)(void *, bool); |
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
98,6 → 101,7 |
uint8_t *glyphs; |
rgb_conv_t rgb_conv; |
mask_conv_t mask_conv; |
} screen; |
/** Backbuffer character cell. */ |
226,10 → 230,15 |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = rgb & 0xffffff; |
*((uint32_t *) dst) = rgb & 0x00ffffff; |
} |
static void mask_0888(void *dst, bool mask) |
{ |
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0); |
} |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
250,7 → 259,20 |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
static void mask_888(void *dst, bool mask) |
{ |
if (mask) { |
((uint8_t *) dst)[0] = 0xff; |
((uint8_t *) dst)[1] = 0xff; |
((uint8_t *) dst)[2] = 0xff; |
} else { |
((uint8_t *) dst)[0] = 0; |
((uint8_t *) dst)[1] = 0; |
((uint8_t *) dst)[2] = 0; |
} |
} |
/** BGR 8:8:8 conversion |
* |
*/ |
271,7 → 293,12 |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
static void mask_555(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0x7fff : 0); |
} |
/** RGB 5:6:5 conversion |
* |
*/ |
281,7 → 308,12 |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
static void mask_565(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0xffff : 0); |
} |
/** RGB 3:2:3 |
* |
*/ |
291,20 → 323,30 |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
static void mask_323(void *dst, bool mask) |
{ |
*((uint8_t *) dst) = (mask ? 0xff : 0); |
} |
/** Draw a filled rectangle. |
* |
* @note Need real implementation that does not access VRAM twice. |
* |
*/ |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
unsigned int x, y; |
unsigned int x; |
unsigned int y; |
unsigned int copy_bytes; |
uint8_t *sp, *dp; |
uint8_t *sp; |
uint8_t *dp; |
uint8_t cbuf[4]; |
if (y0 >= y1 || x0 >= x1) return; |
if ((y0 >= y1) || (x0 >= x1)) |
return; |
screen.rgb_conv(cbuf, color); |
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
333,7 → 375,8 |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
unsigned int row, col; |
unsigned int row; |
unsigned int col; |
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
359,7 → 402,7 |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
unsigned i; |
size_t i; |
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
388,12 → 431,15 |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
unsigned int row, col; |
unsigned int x, y; |
unsigned int row; |
unsigned int col; |
unsigned int x; |
unsigned int y; |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp, *xbp; |
bb_cell_t *bbp; |
bb_cell_t *xbp; |
/* |
* Redraw. |
411,9 → 457,9 |
fg_color = xbp->fg_color; |
bg_color = xbp->bg_color; |
if (bbp->glyph == glyph && |
bbp->fg_color == xbp->fg_color && |
bbp->bg_color == xbp->bg_color) { |
if ((bbp->glyph == glyph) |
&& (bbp->fg_color == xbp->fg_color) |
&& (bbp->bg_color == xbp->bg_color)) { |
x += FONT_WIDTH; |
continue; |
} |
451,6 → 497,7 |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
*/ |
static void render_glyphs(void) |
{ |
463,19 → 510,16 |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) { |
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0xffffff : 0x000000); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? true : false); |
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0x000000 : 0xffffff); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? false : true); |
} |
} |
} |
} |
/** Create new viewport |
* |
* @param x Origin of the viewport (x). |
495,6 → 539,7 |
if (!viewports[i].initialized) |
break; |
} |
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
531,16 → 576,15 |
/* |
* Conditions necessary to select aligned version: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
*/ |
if ((word_size % screen.pixelbytes) == 0 && |
(FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
(x * screen.pixelbytes) % word_size == 0 && |
screen.scanline % word_size == 0) { |
if (((word_size % screen.pixelbytes) == 0) |
&& ((FONT_WIDTH * screen.pixelbytes) % word_size == 0) |
&& ((x * screen.pixelbytes) % word_size == 0) |
&& (screen.scanline % word_size == 0)) { |
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
574,39 → 618,47 |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
unsigned int glyphsize; |
uint8_t *glyphs; |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb_conv = rgb_323; |
screen.mask_conv = mask_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb_conv = rgb_555; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb_conv = rgb_565; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
screen.rgb_conv = bgr_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
screen.rgb_conv = rgb_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
screen.rgb_conv = bgr_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
default: |
621,8 → 673,8 |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
glyphs = (uint8_t *) malloc(glyphsize); |
size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) |
return false; |
658,15 → 710,16 |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned int i; |
unsigned int yd; |
unsigned long fg_buf; |
unsigned long bg_buf; |
unsigned long mask; |
unsigned int ww, d_add; |
/* |
* Prepare a pair of words, one filled with foreground-color |
680,16 → 733,16 |
} |
/* Pointer to the current position in the mask. */ |
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
/* Pointer to the current position on the screen. */ |
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
/* Width of the character cell in words. */ |
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
718,14 → 771,17 |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
unsigned int i; |
unsigned int j; |
unsigned int yd; |
uint8_t fg_buf[4]; |
uint8_t bg_buf[4]; |
uint8_t *sp; |
uint8_t b; |
/* Pre-render 1x the foreground and background color pixels. */ |
738,10 → 794,10 |
} |
/* Pointer to the current position on the screen. */ |
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
779,14 → 835,10 |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
(*vport->dglyph)(x, y, cursor, screen.glyphs, glyph, |
fg_color, bg_color); |
} |
874,11 → 926,13 |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* |
*/ |
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
unsigned int i, j; |
unsigned int i; |
unsigned int j; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |
1659,6 → 1713,10 |
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
retval = EOK; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
} |
/branches/network/uspace/srv/fb/ega.c |
---|
391,7 → 391,10 |
} |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = EINVAL; |
} |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.h |
---|
52,6 → 52,7 |
typedef struct tmpfs_dentry { |
fs_index_t index; /**< TMPFS node index. */ |
dev_handle_t dev_handle;/**< Device handle. */ |
link_t dh_link; /**< Dentries hash table link. */ |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
66,6 → 67,8 |
extern libfs_ops_t tmpfs_libfs_ops; |
extern bool tmpfs_init(void); |
extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
177,7 → 177,7 |
goto error; |
tag[5] = 0; |
if (strcmp(tag, "TMPFS") != 0) |
if (str_cmp(tag, "TMPFS") != 0) |
goto error; |
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.c |
---|
128,6 → 128,11 |
{ |
printf(NAME ": HelenOS TMPFS file system server\n"); |
if (!tmpfs_init()) { |
printf(NAME ": failed to initialize TMPFS\n"); |
return -1; |
} |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
58,14 → 58,11 |
#define NAMES_BUCKETS 4 |
/* |
* For now, we don't distinguish between different dev_handles/instances. All |
* requests resolve to the only instance, rooted in the following variable. |
*/ |
static tmpfs_dentry_t *root; |
/** All root nodes have index 0. */ |
#define TMPFS_SOME_ROOT 0 |
/** Global counter for assigning node indices. Shared by all instances. */ |
fs_index_t tmpfs_next_index = 1; |
#define TMPFS_DEV 0 /**< Dummy device handle for TMPFS */ |
/* |
* Implementation of the libfs interface. |
*/ |
102,7 → 99,7 |
static void *tmpfs_root_get(dev_handle_t dev_handle) |
{ |
return root; |
return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT); |
} |
static char tmpfs_plb_get_char(unsigned pos) |
142,18 → 139,22 |
/** Hash table of all directory entries. */ |
hash_table_t dentries; |
#define DENTRIES_KEY_INDEX 0 |
#define DENTRIES_KEY_DEV 1 |
/* Implementation of hash table interface for the dentries hash table. */ |
static hash_index_t dentries_hash(unsigned long *key) |
static hash_index_t dentries_hash(unsigned long key[]) |
{ |
return *key % DENTRIES_BUCKETS; |
return key[DENTRIES_KEY_INDEX] % DENTRIES_BUCKETS; |
} |
static int dentries_compare(unsigned long *key, hash_count_t keys, |
static int dentries_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t, |
dh_link); |
return dentry->index == *key; |
return (dentry->index == key[DENTRIES_KEY_INDEX] && |
dentry->dev_handle == key[DENTRIES_KEY_DEV]); |
} |
static void dentries_remove_callback(link_t *item) |
167,8 → 168,6 |
.remove_callback = dentries_remove_callback |
}; |
fs_index_t tmpfs_next_index = 1; |
typedef struct { |
char *name; |
tmpfs_dentry_t *parent; |
215,6 → 214,7 |
static bool tmpfs_dentry_initialize(tmpfs_dentry_t *dentry) |
{ |
dentry->index = 0; |
dentry->dev_handle = 0; |
dentry->sibling = NULL; |
dentry->child = NULL; |
dentry->type = TMPFS_NONE; |
226,15 → 226,21 |
&names_ops); |
} |
static bool tmpfs_init(void) |
bool tmpfs_init(void) |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 2, &dentries_ops)) |
return false; |
root = (tmpfs_dentry_t *) tmpfs_create_node(TMPFS_DEV, L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return true; |
} |
static bool tmpfs_instance_init(dev_handle_t dev_handle) |
{ |
tmpfs_dentry_t *root; |
root = (tmpfs_dentry_t *) tmpfs_create_node(dev_handle, L_DIRECTORY); |
if (!root) |
return false; |
} |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
255,7 → 261,7 |
link_t *hlp = hash_table_find(&childp->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, link); |
return !strcmp(namep->name, component); |
return !str_cmp(namep->name, component); |
} |
void *tmpfs_match(void *prnt, const char *component) |
272,8 → 278,11 |
void * |
tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
unsigned long key = index; |
link_t *lnk = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = index, |
[DENTRIES_KEY_DEV] = dev_handle |
}; |
link_t *lnk = hash_table_find(&dentries, key); |
if (!lnk) |
return NULL; |
return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link); |
296,7 → 305,11 |
free(node); |
return NULL; |
} |
if (!tmpfs_root_get(dev_handle)) |
node->index = TMPFS_SOME_ROOT; |
else |
node->index = tmpfs_next_index++; |
node->dev_handle = dev_handle; |
if (lflag & L_DIRECTORY) |
node->type = TMPFS_DIRECTORY; |
else |
303,8 → 316,11 |
node->type = TMPFS_FILE; |
/* Insert the new node into the dentry hash table. */ |
unsigned long key = node->index; |
hash_table_insert(&dentries, &key, &node->dh_link); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = node->index, |
[DENTRIES_KEY_DEV] = node->dev_handle |
}; |
hash_table_insert(&dentries, key, &node->dh_link); |
return (void *) node; |
} |
319,13 → 335,13 |
if (!namep) |
return ENOMEM; |
tmpfs_name_initialize(namep); |
size_t len = strlen(nm); |
namep->name = malloc(len + 1); |
size_t size = str_size(nm); |
namep->name = malloc(size + 1); |
if (!namep->name) { |
free(namep); |
return ENOMEM; |
} |
strcpy(namep->name, nm); |
str_cpy(namep->name, size + 1, nm); |
namep->parent = parentp; |
childp->lnkcnt++; |
384,8 → 400,11 |
assert(!dentry->child); |
assert(!dentry->sibling); |
unsigned long key = dentry->index; |
hash_table_remove(&dentries, &key, 1); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = dentry->index, |
[DENTRIES_KEY_DEV] = dentry->dev_handle |
}; |
hash_table_remove(&dentries, key, 2); |
hash_table_destroy(&dentry->names); |
399,13 → 418,36 |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* Initialize TMPFS. */ |
if (!root && !tmpfs_init()) { |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
if (dev_handle >= 0) { |
/* Initialize TMPFS instance. */ |
if (!tmpfs_instance_init(dev_handle)) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
tmpfs_dentry_t *root = tmpfs_root_get(dev_handle); |
if (str_cmp(opts, "restore") == 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
441,8 → 483,11 |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = index, |
[DENTRIES_KEY_DEV] = dev_handle, |
}; |
hlp = hash_table_find(&dentries, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
454,8 → 499,8 |
* Receive the read request. |
*/ |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
463,7 → 508,7 |
size_t bytes; |
if (dentry->type == TMPFS_FILE) { |
bytes = max(0, min(dentry->size - pos, len)); |
bytes = max(0, min(dentry->size - pos, size)); |
(void) ipc_data_read_finalize(callid, dentry->data + pos, |
bytes); |
} else { |
494,7 → 539,7 |
link); |
(void) ipc_data_read_finalize(callid, namep->name, |
strlen(namep->name) + 1); |
str_size(namep->name) + 1); |
bytes = 1; |
} |
514,8 → 559,11 |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = index, |
[DENTRIES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&dentries, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
527,8 → 575,8 |
* Receive the write request. |
*/ |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
537,13 → 585,13 |
/* |
* Check whether the file needs to grow. |
*/ |
if (pos + len <= dentry->size) { |
if (pos + size <= dentry->size) { |
/* The file size is not changing. */ |
(void) ipc_data_write_finalize(callid, dentry->data + pos, len); |
ipc_answer_2(rid, EOK, len, dentry->size); |
(void) ipc_data_write_finalize(callid, dentry->data + pos, size); |
ipc_answer_2(rid, EOK, size, dentry->size); |
return; |
} |
size_t delta = (pos + len) - dentry->size; |
size_t delta = (pos + size) - dentry->size; |
/* |
* At this point, we are deliberately extremely straightforward and |
* simply realloc the contents of the file on every write that grows the |
561,8 → 609,8 |
memset(newdata + dentry->size, 0, delta); |
dentry->size += delta; |
dentry->data = newdata; |
(void) ipc_data_write_finalize(callid, dentry->data + pos, len); |
ipc_answer_2(rid, EOK, len, dentry->size); |
(void) ipc_data_write_finalize(callid, dentry->data + pos, size); |
ipc_answer_2(rid, EOK, size, dentry->size); |
} |
void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
575,8 → 623,11 |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = index, |
[DENTRIES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&dentries, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
610,8 → 661,11 |
int rc; |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[DENTRIES_KEY_INDEX] = index, |
[DENTRIES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&dentries, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
/branches/network/uspace/srv/fs/fat/fat_dentry.c |
---|
62,15 → 62,18 |
int fat_dentry_namecmp(char *name, const char *component) |
{ |
int rc; |
size_t size; |
if (!(rc = stricmp(name, component))) |
return rc; |
if (!strchr(name, '.')) { |
if (!str_chr(name, '.')) { |
/* |
* There is no '.' in the name, so we know that there is enough |
* space for appending an extra '.' to name. |
*/ |
name[strlen(name)] = '.'; |
name[strlen(name) + 1] = '\0'; |
size = str_size(name); |
name[size] = '.'; |
name[size + 1] = '\0'; |
rc = stricmp(name, component); |
} |
return rc; |
/branches/network/uspace/srv/fs/fat/fat_ops.c |
---|
487,10 → 487,10 |
b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE); |
d = (fat_dentry_t *)b->data; |
if (fat_classify_dentry(d) == FAT_DENTRY_LAST || |
strcmp(d->name, FAT_NAME_DOT) == 0) { |
str_cmp(d->name, FAT_NAME_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
strcpy(d->name, FAT_NAME_DOT); |
strcpy(d->ext, FAT_EXT_PAD); |
str_cpy(d->name, 8, FAT_NAME_DOT); |
str_cpy(d->ext, 3, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = host2uint16_t_le(childp->firstc); |
/* TODO: initialize also the date/time members. */ |
497,10 → 497,10 |
} |
d++; |
if (fat_classify_dentry(d) == FAT_DENTRY_LAST || |
strcmp(d->name, FAT_NAME_DOT_DOT) == 0) { |
str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
strcpy(d->name, FAT_NAME_DOT_DOT); |
strcpy(d->ext, FAT_EXT_PAD); |
str_cpy(d->name, 8, FAT_NAME_DOT_DOT); |
str_cpy(d->ext, 3, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? |
host2uint16_t_le(FAT_CLST_RES0) : |
755,6 → 755,28 |
uint16_t rde; |
int rc; |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
/* initialize libblock */ |
rc = block_init(dev_handle, BS_SIZE); |
if (rc != EOK) { |
937,7 → 959,7 |
ipc_answer_1(rid, ENOENT, 0); |
return; |
hit: |
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
(void) ipc_data_read_finalize(callid, name, str_size(name) + 1); |
bytes = (pos - spos) + 1; |
} |
/branches/network/uspace/srv/pci/libpci/names.c |
---|
103,7 → 103,7 |
u32 id34 = id_pair(id3, id4); |
unsigned int h = id_hash(cat, id12, id34); |
struct id_entry *n = a->id_hash[h]; |
int len = strlen((char *) text); |
int len = str_size((char *) text); |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
/branches/network/uspace/srv/devmap/devmap.c |
---|
563,7 → 563,7 |
ipc_answer_0(iid, EOK); |
size_t name_size = strlen(device->name); |
size_t name_size = str_size(device->name); |
/* FIXME: |
* We have no channel from DEVMAP to client, therefore |
/branches/network/uspace/srv/vfs/vfs_ops.c |
---|
60,6 → 60,7 |
link_t link; |
char *fs_name; /**< File system name */ |
char *mp; /**< Mount point */ |
char *opts; /**< Mount options. */ |
ipc_callid_t callid; /**< Call ID waiting for the mount */ |
ipc_callid_t rid; /**< Request ID */ |
dev_handle_t dev_handle; /**< Device handle */ |
80,18 → 81,21 |
}; |
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
fs_handle_t fs_handle, char *mp) |
fs_handle_t fs_handle, char *mp, char *opts) |
{ |
/* Resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
vfs_node_t *mp_node = NULL; |
int rc; |
ipcarg_t rc; |
int phone; |
aid_t msg; |
ipc_call_t answer; |
/* Resolve the path to the mountpoint. */ |
futex_down(&rootfs_futex); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
rwlock_write_lock(&namespace_rwlock); |
if ((strlen(mp) == 1) && (mp[0] == '/')) { |
if (str_cmp(mp, "/") == 0) { |
/* Trying to mount root FS over root FS */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
124,12 → 128,12 |
rwlock_write_unlock(&namespace_rwlock); |
} else { |
/* We still don't have the root file system mounted. */ |
if ((strlen(mp) == 1) && (mp[0] == '/')) { |
if (str_cmp(mp, "/") == 0) { |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
fs_index_t rindex; |
size_t rsize; |
unsigned rlnkcnt; |
/* |
* For this simple, but important case, |
138,9 → 142,20 |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
msg = async_send_1(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &answer); |
/* 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); |
futex_up(&rootfs_futex); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc != EOK) { |
futex_up(&rootfs_futex); |
148,11 → 163,15 |
return; |
} |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
rsize = (size_t) IPC_GET_ARG2(answer); |
rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
mr_res.triplet.index = rindex; |
mr_res.size = rsize; |
mr_res.lnkcnt = rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
rootfs.fs_handle = fs_handle; |
183,12 → 202,24 |
*/ |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
rc = async_req_4_0(phone, VFS_MOUNT, |
msg = async_send_4(phone, VFS_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
(ipcarg_t) dev_handle); |
(ipcarg_t) dev_handle, &answer); |
/* 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); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc != EOK) { |
/* Mount failed, drop reference to mp_node. */ |
216,10 → 247,12 |
ipc_answer_0(pr->callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp, |
pr->opts); |
free(pr->fs_name); |
free(pr->mp); |
free(pr->opts); |
list_remove(cur); |
free(pr); |
goto loop; |
272,12 → 305,47 |
/* Deliver the mount point. */ |
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, retval); |
free(mp); |
return; |
} |
mp[size] = '\0'; |
/* Now we expect to receive the mount options. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Check the offered options size. */ |
if (size < 0 || size > MAX_MNTOPTS_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Allocate buffer for the mount options. */ |
char *opts = (char *) malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
return; |
} |
/* Deliver the mount options. */ |
retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
286,6 → 354,7 |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
297,6 → 366,7 |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
306,8 → 376,9 |
char *fs_name = (char *) malloc(size + 1); |
if (fs_name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(opts); |
return; |
} |
314,8 → 385,9 |
/* Deliver the file system name. */ |
retval = ipc_data_write_finalize(callid, fs_name, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
322,6 → 394,21 |
fs_name[size] = '\0'; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
ipc_call_t data; |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
328,18 → 415,22 |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
if (flags & IPC_FLAG_BLOCKING) { |
pending_req_t *pr; |
/* Blocking mount, add to pending list */ |
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
if (!pr) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(fs_name); |
free(opts); |
return; |
} |
pr->fs_name = fs_name; |
pr->mp = mp; |
pr->opts = opts; |
pr->callid = callid; |
pr->rid = rid; |
pr->dev_handle = dev_handle; |
352,6 → 443,7 |
ipc_answer_0(rid, ENOENT); |
free(mp); |
free(fs_name); |
free(opts); |
return; |
} |
359,9 → 451,10 |
ipc_answer_0(callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
free(mp); |
free(fs_name); |
free(opts); |
} |
void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
804,37 → 897,37 |
void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
{ |
size_t len; |
size_t olen, nlen; |
ipc_callid_t callid; |
int rc; |
/* Retrieve the old path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
if (!ipc_data_write_receive(&callid, &olen)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *old = malloc(len + 1); |
char *old = malloc(olen + 1); |
if (!old) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, old, len))) { |
if ((rc = ipc_data_write_finalize(callid, old, olen))) { |
ipc_answer_0(rid, rc); |
free(old); |
return; |
} |
old[len] = '\0'; |
old[olen] = '\0'; |
/* Retrieve the new path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
if (!ipc_data_write_receive(&callid, &nlen)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(old); |
return; |
} |
char *new = malloc(len + 1); |
char *new = malloc(nlen + 1); |
if (!new) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
841,16 → 934,16 |
free(old); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, new, len))) { |
if ((rc = ipc_data_write_finalize(callid, new, nlen))) { |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
new[len] = '\0'; |
new[nlen] = '\0'; |
char *oldc = canonify(old, &len); |
char *newc = canonify(new, NULL); |
char *oldc = canonify(old, &olen); |
char *newc = canonify(new, &nlen); |
if (!oldc || !newc) { |
ipc_answer_0(rid, EINVAL); |
free(old); |
857,7 → 950,9 |
free(new); |
return; |
} |
if (!strncmp(newc, oldc, len)) { |
oldc[olen] = '\0'; |
newc[nlen] = '\0'; |
if (!str_lcmp(newc, oldc, str_length(oldc))) { |
/* oldc is a prefix of newc */ |
ipc_answer_0(rid, EINVAL); |
free(old); |
/branches/network/uspace/srv/vfs/vfs_register.c |
---|
376,8 → 376,7 |
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 (strncmp(fs->vfs_info.name, name, |
sizeof(fs->vfs_info.name)) == 0) { |
if (str_cmp(fs->vfs_info.name, name) == 0) { |
handle = fs->fs_handle; |
break; |
} |
/branches/network/uspace/srv/vfs/vfs.h |
---|
254,6 → 254,8 |
extern uint8_t *plb; /**< Path Lookup Buffer */ |
extern link_t plb_head; /**< List of active PLB entries. */ |
#define MAX_MNTOPTS_LEN 256 |
/** Holding this rwlock prevents changes in file system namespace. */ |
extern rwlock_t namespace_rwlock; |