Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4344 → Rev 4345

/branches/dynload/uspace/app/init/init.c
27,9 → 27,9
*/
 
/** @addtogroup init Init
* @brief Init process for testing purposes.
* @brief Init process for user space environment configuration.
* @{
*/
*/
/**
* @file
*/
36,6 → 36,7
 
#include <stdio.h>
#include <unistd.h>
#include <ipc/ipc.h>
#include <vfs/vfs.h>
#include <bool.h>
#include <errno.h>
42,26 → 43,17
#include <fcntl.h>
#include <task.h>
#include <malloc.h>
#include <macros.h>
#include "init.h"
#include "version.h"
 
#define BUF_SIZE 150000
 
static char *buf;
 
static void console_wait(void)
{
while (get_cons_phone() < 0)
usleep(50000); // FIXME
}
 
static bool mount_fs(const char *fstype)
{
int rc = -1;
while (rc < 0) {
rc = mount(fstype, "/", "initrd");
 
rc = mount(fstype, "/", "initrd", IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted\n");
75,8 → 67,6
case ENOENT:
printf(NAME ": Unknown filesystem type (%s)\n", fstype);
return false;
default:
sleep(5); // FIXME
}
}
86,24 → 76,25
static void spawn(char *fname)
{
char *argv[2];
 
printf(NAME ": Spawning %s\n", fname);
 
argv[0] = fname;
argv[1] = NULL;
 
if (task_spawn(fname, argv) != 0) {
/* Success */
sleep(1);
}
if (task_spawn(fname, argv))
/* Add reasonable delay to avoid
intermixed klog output */
usleep(10000);
else
printf(NAME ": Error spawning %s\n", fname);
}
 
int main(int argc, char *argv[])
{
info_print();
sleep(5); // FIXME
if (!mount_fs("tmpfs") && !mount_fs("fat")) {
if (!mount_fs(STRING(RDFMT))) {
printf(NAME ": Exiting\n");
return -1;
}
121,7 → 112,6
spawn("/app/klog");
spawn("/app/bdsh");
free(buf);
return 0;
}
 
/branches/dynload/uspace/app/tester/devmap/devmap1.c
132,12 → 132,10
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
 
while (phone < 0) {
usleep(100000);
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_DRIVER, 0);
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf("Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
/branches/dynload/uspace/app/tester/vfs/vfs1.c
45,7 → 45,7
{
int rc;
 
rc = mount("tmpfs", "/", "nulldev0");
rc = mount("tmpfs", "/", "nulldev0", 0);
switch (rc) {
case EOK:
if (!quiet)
/branches/dynload/uspace/app/tetris/input.c
58,6 → 58,7
 
#include <async.h>
#include <ipc/console.h>
#include <kbd/kbd.h>
 
/* return true iff the given timeval is positive */
#define TV_POS(tv) \
111,8 → 112,9
s = NULL;
 
if (!lastchar) {
again:
if (!getchar_inprog) {
cons_phone = get_cons_phone();
cons_phone = get_console_phone();
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETKEY, 0, 0, &charcall);
}
127,6 → 129,9
if (rc) {
stop("end of file, help");
}
if (IPC_GET_ARG1(charcall) == KE_RELEASE)
goto again;
 
lastchar = IPC_GET_ARG4(charcall);
}
if (tvp) {
/branches/dynload/uspace/app/klog/klog.c
27,9 → 27,9
*/
 
/** @addtogroup klog KLog
* @brief HelenOS KLog
* @brief HelenOS KLog
* @{
*/
*/
/**
* @file
*/
50,12 → 50,6
/* Pointer to klog area */
static char *klog;
 
static void console_wait(void)
{
while (get_cons_phone() < 0)
usleep(50000); // FIXME
}
 
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
async_serialize_start();
/branches/dynload/uspace/lib/libblock/libblock.c
27,15 → 27,15
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libblock
/** @addtogroup libblock
* @{
*/
*/
/**
* @file
* @brief
*/
 
#include "libblock.h"
#include "libblock.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <ipc/devmap.h>
146,7 → 146,7
if (!com_area) {
return ENOMEM;
}
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
dev_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
/branches/dynload/uspace/lib/libc/include/vfs/vfs.h
39,7 → 39,8
 
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 unsigned int flags);
 
#endif
 
/branches/dynload/uspace/lib/libc/include/async.h
76,7 → 76,7
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
 
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
86,8 → 86,8
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
suseconds_t timeout);
 
fid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t,ipc_call_t *));
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
void async_usleep(suseconds_t timeout);
void async_create_manager(void);
void async_destroy_manager(void);
/branches/dynload/uspace/lib/libc/include/io/stream.h
47,7 → 47,8
extern ssize_t write_stdout(const void *, size_t);
extern ssize_t write_stderr(const void *, size_t);
 
extern int get_cons_phone(void);
extern int get_console_phone(void);
extern void console_wait(void);
 
#endif
 
/branches/dynload/uspace/lib/libc/include/ipc/ipc.h
246,8 → 246,11
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int);
 
#define IPC_FLAG_BLOCKING 0x01
 
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *);
extern int ipc_connect_me_to(int, int, int, int);
extern int ipc_connect_me_to_blocking(int, int, int, int);
extern int ipc_hangup(int);
extern int ipc_register_irq(int, int, int, irq_code_t *);
extern int ipc_unregister_irq(int, int);
/branches/dynload/uspace/lib/libc/include/ipc/services.h
30,8 → 30,8
* @{
*/
/**
* @file services.h
* @brief List of all known services and their codes.
* @file services.h
* @brief List of all known services and their codes.
*/
 
#ifndef LIBIPC_SERVICES_H_
/branches/dynload/uspace/lib/libc/include/sys/types.h
42,6 → 42,10
typedef long off_t;
typedef int mode_t;
 
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/generic/ddi.c
33,6 → 33,7
*/
 
#include <ddi.h>
#include <libarch/ddi.h>
#include <libc.h>
#include <task.h>
#include <as.h>
/branches/dynload/uspace/lib/libc/generic/kbd.c
41,7 → 41,7
 
int kbd_get_event(kbd_event_t *ev)
{
int console_phone = get_cons_phone();
int console_phone = get_console_phone();
ipcarg_t r0, r1, r2, r3;
int rc;
 
/branches/dynload/uspace/lib/libc/generic/console.c
39,25 → 39,25
 
void console_clear(void)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_0(cons_phone, CONSOLE_CLEAR);
}
 
void console_goto(int row, int col)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_2(cons_phone, CONSOLE_GOTO, row, col);
}
 
void console_flush(void)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_0(cons_phone, CONSOLE_FLUSH);
}
 
int console_get_size(int *rows, int *cols)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
ipcarg_t r, c;
int rc;
 
71,25 → 71,25
 
void console_set_style(int style)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int fg_color, int bg_color, int flags)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int fg_color, int bg_color)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int show)
{
int cons_phone = get_cons_phone();
int cons_phone = get_console_phone();
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
}
 
/branches/dynload/uspace/lib/libc/generic/loader.c
62,7 → 62,7
loader_t *ldr;
int phone_id;
 
phone_id = ipc_connect_me_to(PHONE_NS, SERVICE_LOAD, 0, 0);
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
 
/branches/dynload/uspace/lib/libc/generic/ipc.c
598,7 → 598,7
ipcarg_t newphid;
int res;
 
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
NULL, NULL, NULL, NULL, &newphid);
if (res)
return res;
605,6 → 605,30
return newphid;
}
 
/** Ask through phone for a new connection to some service.
*
* If the connection is not available at the moment, the
* call will block.
*
* @param phoneid Phone handle used for contacting the other side.
* @param arg1 User defined argument.
* @param arg2 User defined argument.
* @param arg3 User defined argument.
*
* @return New phone handle on success or a negative error code.
*/
int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3)
{
ipcarg_t newphid;
int res;
 
res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
if (res)
return res;
return newphid;
}
 
/** Hang up a phone.
*
* @param phoneid Handle of the phone to be hung up.
/branches/dynload/uspace/lib/libc/generic/vfs/vfs.c
31,7 → 31,7
*/
/** @file
*/
 
#include <vfs/vfs.h>
#include <vfs/canonify.h>
#include <stdlib.h>
57,7 → 57,7
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_len = 0;
size_t cwd_len = 0;
 
char *absolutize(const char *path, size_t *retlen)
{
109,34 → 109,39
return ncwd_path;
}
 
static int vfs_connect(void)
static void vfs_connect(void)
{
if (vfs_phone < 0)
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
return vfs_phone;
while (vfs_phone < 0)
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
}
 
static int device_get_handle(const char *name, dev_handle_t *handle)
static int device_get_handle(const char *name, dev_handle_t *handle,
const unsigned int flags)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
int phone;
if (flags & IPC_FLAG_BLOCKING)
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
else
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
if (phone < 0)
return phone;
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0,
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
&answer);
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
ipc_hangup(phone);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
149,7 → 154,8
return retval;
}
 
int mount(const char *fs_name, const char *mp, const char *dev)
int mount(const char *fs_name, const char *mp, const char *dev,
const unsigned int flags)
{
int res;
ipcarg_t rc;
156,7 → 162,7
aid_t req;
dev_handle_t dev_handle;
res = device_get_handle(dev, &dev_handle);
res = device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
164,20 → 170,13
char *mpa = absolutize(mp, &mpa_len);
if (!mpa)
return ENOMEM;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(mpa);
return res;
}
}
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL);
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name));
vfs_connect();
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL);
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
185,8 → 184,8
free(mpa);
return (int) rc;
}
/* Ask VFS whether it likes fs_name. */
rc = async_req_0_0(vfs_phone, IPC_M_PING);
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, strlen(fs_name));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
194,24 → 193,17
free(mpa);
return (int) rc;
}
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
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);
free(mpa);
return (int) rc;
}
 
static int _open(const char *path, int lflag, int oflag, ...)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
223,15 → 215,8
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
if (rc != EOK) {
258,22 → 243,14
 
int close(int fildes)
{
int res;
ipcarg_t rc;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
 
async_serialize_end();
futex_up(&vfs_phone_futex);
282,7 → 259,6
 
ssize_t read(int fildes, void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
289,14 → 265,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
316,7 → 286,6
 
ssize_t write(int fildes, const void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
323,14 → 292,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
350,20 → 313,12
 
off_t lseek(int fildes, off_t offset, int whence)
{
int res;
ipcarg_t rc;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
&newoffs);
379,19 → 334,12
 
int ftruncate(int fildes, off_t length)
{
int res;
ipcarg_t rc;
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
async_serialize_end();
futex_up(&vfs_phone_futex);
433,7 → 381,6
 
int mkdir(const char *path, mode_t mode)
{
int res;
ipcarg_t rc;
aid_t req;
441,18 → 388,11
char *pa = absolutize(path, &pa_len);
if (!pa)
return ENOMEM;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
if (rc != EOK) {
471,7 → 411,6
 
static int _unlink(const char *path, int lflag)
{
int res;
ipcarg_t rc;
aid_t req;
482,15 → 421,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
if (rc != EOK) {
519,7 → 451,6
 
int rename(const char *old, const char *new)
{
int res;
ipcarg_t rc;
aid_t req;
537,16 → 468,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(olda);
free(newa);
return res;
}
}
vfs_connect();
req = async_send_0(vfs_phone, VFS_RENAME, NULL);
rc = ipc_data_write_start(vfs_phone, olda, olda_len);
if (rc != EOK) {
/branches/dynload/uspace/lib/libc/generic/io/stream.c
115,11 → 115,19
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
int get_cons_phone(void)
int get_console_phone(void)
{
open_console();
if (console_phone < 0)
console_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_CONSOLE, 0, 0);
return console_phone;
}
 
void console_wait(void)
{
while (console_phone < 0)
get_console_phone();
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/sparc64/include/ddi.h
0,0 → 1,92
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libsparc64
*/
 
#ifndef LIBC_sparc64_DDI_H_
#define LIBC_sparc64_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline memory_barrier(void)
{
asm volatile ("membar #LoadLoad | #StoreStore\n" ::: "memory");
}
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
memory_barrier();
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
#endif
/branches/dynload/uspace/lib/libc/arch/ia64/include/ddi.h
1,5 → 1,5
/*
* Copyright (c) 2005 Jakub Jermar, Jakub Vana
* Copyright (c) 2005 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64
/** @addtogroup libcia64
* @{
*/
/** @file
35,63 → 35,80
#ifndef LIBC_ia64_DDI_H_
#define LIBC_ia64_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
typedef uint64_t ioport_t;
#define IO_SPACE_BOUNDARY (64 * 1024)
 
uint64_t get_ia64_iospace_address(void);
 
extern uint64_t ia64_iospace_address;
 
#define IA64_IOSPACE_ADDRESS (ia64_iospace_address?ia64_iospace_address:(ia64_iospace_address=get_ia64_iospace_address()))
#define IA64_IOSPACE_ADDRESS \
(ia64_iospace_address ? \
ia64_iospace_address : \
(ia64_iospace_address = get_ia64_iospace_address()))
 
static inline void outb(ioport_t port,uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((uint8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outw(ioport_t port,uint16_t v)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((uint16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outl(ioport_t port,uint32_t v)
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((uint32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
 
static inline uint8_t inb(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
return *((uint8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint16_t inw(ioport_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 ))));
return *((uint16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint32_t inl(ioport_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
return *((uint32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
 
 
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/arch/arm32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcarm32
*/
 
#ifndef LIBC_arm32_DDI_H_
#define LIBC_arm32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/dynload/uspace/lib/libc/arch/ppc32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcppc32
*/
 
#ifndef LIBC_ppc32_DDI_H_
#define LIBC_ppc32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/dynload/uspace/lib/libc/arch/mips32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcmips32
*/
 
#ifndef LIBC_mips32_DDI_H_
#define LIBC_mips32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/dynload/uspace/lib/libc/arch/ia32/include/ddi.h
33,45 → 33,72
#ifndef LIBC_ia32_DDI_H_
#define LIBC_ia32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
#define IO_SPACE_BOUNDARY ((void *) (64 * 1024))
 
static inline void outb(int16_t port, uint8_t b)
static inline uint8_t pio_read_8(ioport8_t *port)
{
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port));
uint8_t val;
asm volatile (
"inb %w[port], %b[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline void outw(int16_t port, int16_t w)
static inline uint16_t pio_read_16(ioport16_t *port)
{
asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port));
uint16_t val;
asm volatile (
"inw %w[port], %w[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline void outl(int16_t port, uint32_t l)
static inline uint32_t pio_read_32(ioport32_t *port)
{
asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port));
uint32_t val;
asm volatile (
"inl %w[port], %[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline uint8_t inb(int16_t port)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
uint8_t val;
 
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outb %b[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
static inline int16_t inw(int16_t port)
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
int16_t val;
 
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outw %w[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
static inline uint32_t inl(int16_t port)
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
uint32_t val;
 
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outl %[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
#endif
/branches/dynload/uspace/srv/kbd/port/ns16550.c
86,20 → 86,22
 
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 
uint16_t ns16550_port;
static uintptr_t ns16550_physical;
static uintptr_t ns16550_kernel;
 
int kbd_port_init(void)
{
void *vaddr;
 
async_set_interrupt_received(ns16550_irq_handler);
 
ns16550_port = sysinfo_value("kbd.port");
ns16550_kbd.cmds[0].addr = (void *) (ns16550_port + LSR_REG);
ns16550_kbd.cmds[3].addr = (void *) (ns16550_port + RBR_REG);
ns16550_physical = sysinfo_value("kbd.address.physical");
ns16550_kernel = sysinfo_value("kbd.address.kernel");
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"), sysinfo_value("kbd.devno"),
0, &ns16550_kbd);
iospace_enable(task_get_id(), ns16550_port, 8);
 
return 0;
return pio_enable((void *) ns16550_physical, 8, &vaddr);
}
 
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
/branches/dynload/uspace/srv/kbd/port/i8042.c
35,6 → 35,8
* @brief i8042 port driver.
*/
 
#include <ddi.h>
#include <libarch/ddi.h>
#include <ipc/ipc.h>
#include <async.h>
#include <unistd.h>
66,7 → 68,7
static irq_cmd_t i8042_cmds[] = {
{
.cmd = CMD_PIO_READ_8,
.addr = (void *) 0x64,
.addr = NULL, /* will be patched in run-time */
.dstarg = 1
},
{
82,7 → 84,7
},
{
.cmd = CMD_PIO_READ_8,
.addr = (void *) 0x60,
.addr = NULL, /* will be patched in run-time */
.dstarg = 2
},
{
95,9 → 97,13
i8042_cmds
};
 
static uintptr_t i8042_physical;
static uintptr_t i8042_kernel;
static i8042_t * i8042;
 
static void wait_ready(void) {
while (i8042_status_read() & i8042_INPUT_FULL)
;
while (pio_read_8(&i8042->status) & i8042_INPUT_FULL)
;
}
 
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call);
104,50 → 110,32
 
int kbd_port_init(void)
{
// int i;
int mouseenabled = 0;
void *vaddr;
 
i8042_physical = sysinfo_value("kbd.address.physical");
i8042_kernel = sysinfo_value("kbd.address.kernel");
if (pio_enable((void *) i8042_physical, sizeof(i8042_t), &vaddr) != 0)
return -1;
i8042 = vaddr;
 
async_set_interrupt_received(i8042_irq_handler);
iospace_enable(task_get_id(), (void *) i8042_DATA, 5);
 
/* Disable kbd, enable mouse */
i8042_command_write(i8042_CMD_KBD);
pio_write_8(&i8042->status, i8042_CMD_KBD);
wait_ready();
i8042_command_write(i8042_CMD_KBD);
pio_write_8(&i8042->status, i8042_CMD_KBD);
wait_ready();
i8042_data_write(i8042_KBD_DISABLE);
pio_write_8(&i8042->data, i8042_KBD_DISABLE);
wait_ready();
 
/* Flush all current IO */
while (i8042_status_read() & i8042_OUTPUT_FULL)
i8042_data_read();
while (pio_read_8(&i8042->status) & i8042_OUTPUT_FULL)
(void) pio_read_8(&i8042->data);
/* Initialize mouse */
/* i8042_command_write(i8042_CMD_MOUSE);
wait_ready();
i8042_data_write(MOUSE_OUT_INIT);
wait_ready();
int mouseanswer = 0;
for (i=0;i < 1000; i++) {
int status = i8042_status_read();
if (status & i8042_OUTPUT_FULL) {
int data = i8042_data_read();
if (status & i8042_MOUSE_DATA) {
mouseanswer = data;
break;
}
}
usleep(1000);
}*/
// if (mouseanswer == MOUSE_ACK) {
// /* enable mouse */
// mouseenabled = 1;
//
// ipc_register_irq(sysinfo_value("mouse.inr"), sysinfo_value("mouse.devno"), 0, &i8042_kbd);
// }
 
/* Enable kbd */
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status;
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data;
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &i8042_kbd);
 
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
154,9 → 142,9
if (mouseenabled)
newcontrol |= i8042_MOUSE_IE;
i8042_command_write(i8042_CMD_KBD);
pio_write_8(&i8042->status, i8042_CMD_KBD);
wait_ready();
i8042_data_write(newcontrol);
pio_write_8(&i8042->data, newcontrol);
wait_ready();
return 0;
167,12 → 155,12
int status = IPC_GET_ARG1(*call);
 
if ((status & i8042_MOUSE_DATA))
return 0;
return;
 
int scan_code = IPC_GET_ARG2(*call);
 
kbd_push_scancode(scan_code);
return 1;
return;
}
 
/**
/branches/dynload/uspace/srv/kbd/port/z8530.c
41,6 → 41,7
#include <kbd.h>
#include <kbd_port.h>
#include <sys/types.h>
#include <ddi.h>
 
#define CHAN_A_STATUS 4
#define CHAN_A_DATA 6
84,9 → 85,9
int kbd_port_init(void)
{
async_set_interrupt_received(z8530_irq_handler);
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual") +
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") +
CHAN_A_STATUS;
z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.virtual") +
z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.kernel") +
CHAN_A_DATA;
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"),
sysinfo_value("kbd.inr"), &z8530_kbd);
/branches/dynload/uspace/srv/kbd/port/i8042.h
38,36 → 38,16
#ifndef KBD_PORT_i8042_H_
#define KBD_PORT_i8042_H_
 
#include <ddi.h>
#include <libarch/ddi.h>
#include <libarch/types.h>
 
#define i8042_DATA 0x60
#define i8042_STATUS 0X64
struct i8042 {
ioport8_t data;
uint8_t pad[3];
ioport8_t status;
} __attribute__ ((packed));
typedef struct i8042 i8042_t;
 
 
typedef unsigned char u8;
typedef short u16;
 
static inline void i8042_data_write(u8 data)
{
outb(i8042_DATA, data);
}
 
static inline u8 i8042_data_read(void)
{
return inb(i8042_DATA);
}
 
static inline u8 i8042_status_read(void)
{
return inb(i8042_STATUS);
}
 
static inline void i8042_command_write(u8 command)
{
outb(i8042_STATUS, command);
}
 
#endif
 
/**
/branches/dynload/uspace/srv/kbd/generic/kbd.c
183,7 → 183,7
if (cir_service) {
while (cir_phone < 0) {
cir_phone = ipc_connect_me_to(PHONE_NS, cir_service,
cir_phone = ipc_connect_me_to_blocking(PHONE_NS, cir_service,
0, 0);
}
}
/branches/dynload/uspace/srv/kbd/layout/us_dvorak.c
27,9 → 27,9
*/
 
/** @addtogroup kbd
* @brief US Dvorak Simplified Keyboard layout.
* @brief US Dvorak Simplified Keyboard layout.
* @{
*/
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
165,13 → 165,36
static char map_neutral[] = {
[KC_BACKSPACE] = '\b',
[KC_TAB] = '\t',
[KC_ENTER] = '\n'
[KC_ENTER] = '\n',
[KC_SPACE] = ' ',
 
[KC_NSLASH] = '/',
[KC_NTIMES] = '*',
[KC_NMINUS] = '-',
[KC_NPLUS] = '+',
[KC_NENTER] = '\n'
};
 
static char map_numeric[] = {
[KC_N7] = '7',
[KC_N8] = '8',
[KC_N9] = '9',
[KC_N4] = '4',
[KC_N5] = '5',
[KC_N6] = '6',
[KC_N1] = '1',
[KC_N2] = '2',
[KC_N3] = '3',
 
[KC_N0] = '0',
[KC_NPERIOD] = '.'
};
 
static int translate(unsigned int key, char *map, size_t map_length)
{
if (key >= map_length) return 0;
return map[key];
if (key >= map_length)
return 0;
return map[key];
}
 
char layout_parse_ev(kbd_event_t *ev)
183,7 → 206,8
return 0;
 
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(char));
if (c != 0) return c;
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(char));
190,7 → 214,8
else
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(char));
 
if (c != 0) return c;
if (c != 0)
return c;
 
if ((ev->mods & KM_SHIFT) != 0)
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(char));
197,11 → 222,17
else
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(char));
 
if (c != 0 ) return c;
if (c != 0)
return c;
 
if ((ev->mods & KM_NUM_LOCK) != 0)
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(char));
else
c = 0;
 
return c;
}
 
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/ns/ns.c
28,11 → 28,11
 
/** @addtogroup ns
* @{
*/
*/
 
/**
* @file ns.c
* @brief Naming service for HelenOS IPC.
* @file ns.c
* @brief Naming service for HelenOS IPC.
*/
 
 
52,12 → 52,12
#include <ddi.h>
#include <as.h>
 
#define NAME "ns"
#define NAME "ns"
 
#define NS_HASH_TABLE_CHAINS 20
#define NS_HASH_TABLE_CHAINS 20
 
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
static int connect_to_service(ipcarg_t service, ipc_call_t *call,
static void connect_to_service(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
65,6 → 65,7
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
 
/* Static functions implementing NS hash table operations. */
static hash_index_t ns_hash(unsigned long *key);
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
83,14 → 84,22
/** NS hash table item. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
} hashed_service_t;
 
static void *clockaddr = NULL;
static void *klogaddr = NULL;
/** Pending connection structure. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
ipcarg_t arg2; /**< Second argument */
ipcarg_t arg3; /**< Third argument */
} pending_req_t;
 
static link_t pending_req;
 
/** Request for connection to a clonable service. */
typedef struct {
link_t link;
102,10 → 111,13
/** List of clonable-service connection requests. */
static link_t cs_req;
 
static void *clockaddr = NULL;
static void *klogaddr = NULL;
 
/** Return true if @a service is clonable. */
static bool service_clonable(int service)
{
return service == SERVICE_LOAD;
return (service == SERVICE_LOAD);
}
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, void **addr)
128,26 → 140,59
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ);
}
 
/** Process pending connection requests */
static void process_pending_req()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
unsigned long keys[3] = {
pr->service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link)
continue;
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
pr->arg2, pr->arg3, 0, IPC_FF_NONE);
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, retval);
list_remove(cur);
free(pr);
goto loop;
}
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS IPC Naming Service\n");
ipc_call_t call;
ipc_callid_t callid;
ipcarg_t retval;
 
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
&ns_hash_table_ops)) {
printf(NAME ": No memory available\n");
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
 
list_initialize(&pending_req);
list_initialize(&cs_req);
printf(NAME ": Accepting connections\n");
while (1) {
callid = ipc_wait_for_call(&call);
while (true) {
process_pending_req();
ipc_call_t call;
ipc_callid_t callid = ipc_wait_for_call(&call);
ipcarg_t retval;
switch (IPC_GET_METHOD(call)) {
case IPC_M_SHARE_IN:
switch (IPC_GET_ARG3(call)) {
186,8 → 231,9
&call, callid);
continue;
} else {
retval = connect_to_service(IPC_GET_ARG1(call),
&call, callid);
connect_to_service(IPC_GET_ARG1(call), &call,
callid);
continue;
}
break;
default:
194,9 → 240,9
retval = ENOENT;
break;
}
if (!(callid & IPC_CALLID_NOTIFICATION)) {
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
}
/* Not reached */
205,11 → 251,12
 
/** Register service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
* @return Zero on success or a value from @ref errno.h.
* @return Zero on success or a value from @ref errno.h.
*
*/
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
{
218,61 → 265,81
call->in_phone_hash,
0
};
hashed_service_t *hs;
 
if (hash_table_find(&ns_hash_table, keys)) {
if (hash_table_find(&ns_hash_table, keys))
return EEXISTS;
}
hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs) {
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs)
return ENOMEM;
}
link_initialize(&hs->link);
hs->service = service;
hs->phone = phone;
hs->in_phone_hash = call->in_phone_hash;
hash_table_insert(&ns_hash_table, keys, &hs->link);
return 0;
}
 
/** Connect client to service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
{
unsigned long keys[3] = { service, 0, 0 };
link_t *hlp;
hashed_service_t *hs;
 
hlp = hash_table_find(&ns_hash_table, keys);
if (!hlp) {
return ENOENT;
ipcarg_t retval;
unsigned long keys[3] = {
service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link) {
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
/* Blocking connection, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->service = service;
pr->callid = callid;
pr->arg2 = IPC_GET_ARG2(*call);
pr->arg3 = IPC_GET_ARG3(*call);
list_append(&pr->link, &pending_req);
return;
}
retval = ENOENT;
goto out;
}
hs = hash_table_get_instance(hlp, hashed_service_t, link);
return ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/** Register clonable service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
*/
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid)
{
int rc;
cs_req_t *csr;
 
if (list_empty(&cs_req)) {
/* There was no pending connection request. */
printf(NAME ": Unexpected clonable server.\n");
279,56 → 346,54
ipc_answer_0(callid, EBUSY);
return;
}
 
csr = list_get_instance(cs_req.next, cs_req_t, link);
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
list_remove(&csr->link);
 
/* Currently we can only handle a single type of clonable service. */
assert(csr->service == SERVICE_LOAD);
 
ipc_answer_0(callid, EOK);
 
rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
 
free(csr);
}
 
/** Connect client to clonable service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid)
{
int rc;
cs_req_t *csr;
 
assert(service == SERVICE_LOAD);
 
csr = malloc(sizeof(cs_req_t));
cs_req_t *csr = malloc(sizeof(cs_req_t));
if (csr == NULL) {
ipc_answer_0(callid, ENOMEM);
return;
}
 
/* Spawn a loader. */
rc = loader_spawn("loader");
 
int rc = loader_spawn("loader");
if (rc < 0) {
free(csr);
ipc_answer_0(callid, rc);
return;
}
 
csr->service = service;
csr->call = *call;
csr->callid = callid;
 
/*
* We can forward the call only after the server we spawned connects
* to us. Meanwhile we might need to service more connection requests.
340,13 → 405,15
/** Compute hash index into NS hash table.
*
* @param key Pointer keys. However, only the first key (i.e. service number)
* is used to compute the hash index.
* is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
hash_index_t ns_hash(unsigned long *key)
{
assert(key);
return *key % NS_HASH_TABLE_CHAINS;
return (*key % NS_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
357,20 → 424,20
* value. Note that this is close to being classified
* as a nasty hack.
*
* @param key Array of keys.
* @param key Array of keys.
* @param keys Must be lesser or equal to 3.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
hashed_service_t *hs;
 
assert(key);
assert(keys <= 3);
assert(item);
hs = hash_table_get_instance(item, hashed_service_t, link);
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
if (keys == 2)
return key[1] == hs->in_phone_hash;
381,6 → 448,7
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
void ns_remove(link_t *item)
{
388,6 → 456,6
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/**
/**
* @}
*/
/branches/dynload/uspace/srv/console/console.c
509,21 → 509,24
async_set_client_connection(client_connection);
/* Connect to keyboard driver */
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
while (kbd_phone < 0) {
usleep(10000);
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
if (kbd_phone < 0) {
printf(NAME ": Failed to connect to keyboard service\n");
return -1;
}
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
printf(NAME ": Failed to create callback from keyboard service\n");
return -1;
}
async_new_connection(phonehash, 0, NULL, keyboard_events);
/* Connect to framebuffer driver */
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0);
while (fb_info.phone < 0) {
usleep(10000);
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0);
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
if (fb_info.phone < 0) {
printf(NAME ": Failed to connect to video service\n");
return -1;
}
/* Disable kernel output to the console */
/branches/dynload/uspace/srv/rd/rd.c
188,12 → 188,10
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
 
while (phone < 0) {
usleep(10000);
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_DRIVER, 0);
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf(NAME ": Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
/branches/dynload/uspace/srv/loader/main.c
27,12 → 27,12
*/
 
/** @addtogroup loader
* @brief Loads and runs programs from VFS.
* @brief Loads and runs programs from VFS.
* @{
*/
*/
/**
* @file
* @brief Loads and runs programs from VFS.
* @brief Loads and runs programs from VFS.
*
* The program loader is a special init binary. Its image is used
* to create a new task upon a @c task_spawn syscall. The syscall
90,17 → 90,18
ipc_callid_t callid;
task_id_t task_id;
size_t len;
 
task_id = task_get_id();
 
if (!ipc_data_read_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (len > sizeof(task_id)) len = sizeof(task_id);
 
if (len > sizeof(task_id))
len = sizeof(task_id);
ipc_data_read_finalize(callid, &task_id, len);
ipc_answer_0(rid, EOK);
}
116,13 → 117,13
ipc_callid_t callid;
size_t len;
char *name_buf;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
name_buf = malloc(len + 1);
if (!name_buf) {
ipc_answer_0(callid, ENOMEM);
129,15 → 130,15
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, name_buf, len);
ipc_answer_0(rid, EOK);
 
if (pathname != NULL) {
free(pathname);
pathname = NULL;
}
 
name_buf[len] = '\0';
pathname = name_buf;
}
153,23 → 154,23
size_t buf_len, arg_len;
char *p;
int n;
 
if (!ipc_data_write_receive(&callid, &buf_len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (arg_buf != NULL) {
free(arg_buf);
arg_buf = NULL;
}
 
if (argv != NULL) {
free(argv);
argv = NULL;
}
 
arg_buf = malloc(buf_len + 1);
if (!arg_buf) {
ipc_answer_0(callid, ENOMEM);
176,12 → 177,12
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, arg_buf, buf_len);
ipc_answer_0(rid, EOK);
 
arg_buf[buf_len] = '\0';
 
/*
* Count number of arguments
*/
192,10 → 193,10
p = p + arg_len + 1;
++n;
}
 
/* Allocate argv */
argv = malloc((n + 1) * sizeof(char *));
 
if (argv == NULL) {
free(arg_buf);
ipc_answer_0(callid, ENOMEM);
202,7 → 203,7
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* Fill argv with argument pointers
*/
210,12 → 211,12
n = 0;
while (p < arg_buf + buf_len) {
argv[n] = p;
 
arg_len = strlen(p);
p = p + arg_len + 1;
++n;
}
 
argc = n;
argv[n] = NULL;
}
229,7 → 230,7
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
 
rc = elf_load_file(pathname, 0, 0, &prog_info);
if (rc < 0) {
DPRINTF("Failed to load executable '%s'.\n", pathname);
236,12 → 237,12
ipc_answer_0(rid, EINVAL);
return 1;
}
 
elf_create_pcb(&prog_info, &pcb);
 
pcb.argc = argc;
pcb.argv = argv;
 
if (prog_info.interp == NULL) {
/* Statically linked program */
is_dyn_linked = false;
248,7 → 249,7
ipc_answer_0(rid, EOK);
return 0;
}
 
printf("Load ELF interpreter '%s'\n", prog_info.interp);
rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
if (rc < 0) {
257,7 → 258,7
ipc_answer_0(rid, EINVAL);
return 1;
}
 
printf("Run interpreter.\n");
printf("entry point: 0x%lx\n", interp_info.entry);
printf("pcb address: 0x%lx\n", &pcb);
265,7 → 266,7
 
is_dyn_linked = true;
ipc_answer_0(rid, EOK);
 
return 0;
}
 
278,18 → 279,21
*/
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
{
const char *cp;
/* Set the task name. */
task_set_name(pathname);
 
cp = strrchr(pathname, '/');
cp = (cp == NULL) ? pathname : (cp + 1);
task_set_name(cp);
if (is_dyn_linked == true) {
/* Dynamically linked program */
DPRINTF("Run ELF interpreter.\n");
DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
close_console();
 
ipc_answer_0(rid, EOK);
program_run(interp_info.entry, &pcb);
 
} else {
/* Statically linked program */
close_console();
310,24 → 314,25
ipc_callid_t callid;
ipc_call_t call;
int retval;
 
/* Already have a connection? */
if (connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
 
connected = true;
/* Accept the connection */
ipc_answer_0(iid, EOK);
 
/* Ignore parameters, the connection is already open */
(void)iid; (void)icall;
 
(void) iid;
(void) icall;
while (1) {
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
exit(0);
364,18 → 369,18
int main(int argc, char *argv[])
{
ipcarg_t phonead;
 
connected = false;
/* Set a handler of incomming connections. */
async_set_client_connection(loader_connection);
 
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
return -1;
async_manager();
 
/* Never reached */
return 0;
}
/branches/dynload/uspace/srv/fb/ega.c
51,6 → 51,7
#include <libarch/ddi.h>
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
 
#include "ega.h"
#include "../console/screenbuffer.h"
63,7 → 64,7
 
saved_screen saved_screens[MAX_SAVED_SCREENS];
 
#define EGA_IO_ADDRESS 0x3d4
#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
#define EGA_IO_SIZE 2
 
int ega_normal_color = 0x0f;
99,10 → 100,10
 
ega_cursor = col + scr_width * row;
outb(EGA_IO_ADDRESS, 0xe);
outb(EGA_IO_ADDRESS + 1, (ega_cursor >> 8) & 0xff);
outb(EGA_IO_ADDRESS, 0xf);
outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff);
pio_write_8(EGA_IO_BASE, 0xe);
pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff);
pio_write_8(EGA_IO_BASE, 0xf);
pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff);
}
 
static void cursor_disable(void)
109,10 → 110,10
{
uint8_t stat;
 
outb(EGA_IO_ADDRESS, 0xa);
stat=inb(EGA_IO_ADDRESS + 1);
outb(EGA_IO_ADDRESS, 0xa);
outb(EGA_IO_ADDRESS + 1, stat | (1 << 5));
pio_write_8(EGA_IO_BASE, 0xa);
stat = pio_read_8(EGA_IO_BASE + 1);
pio_write_8(EGA_IO_BASE, 0xa);
pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
}
 
static void cursor_enable(void)
119,10 → 120,10
{
uint8_t stat;
 
outb(EGA_IO_ADDRESS, 0xa);
stat=inb(EGA_IO_ADDRESS + 1);
outb(EGA_IO_ADDRESS, 0xa);
outb(EGA_IO_ADDRESS + 1, stat & (~(1 << 5)));
pio_write_8(EGA_IO_BASE, 0xa);
stat = pio_read_8(EGA_IO_BASE + 1);
pio_write_8(EGA_IO_BASE, 0xa);
pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
}
 
static void scroll(int rows)
314,7 → 315,7
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
if(IPC_GET_ARG1(call))
if (IPC_GET_ARG1(call))
cursor_enable();
else
cursor_disable();
380,7 → 381,7
 
style = NORMAL_COLOR;
 
iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2);
iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2);
 
sz = scr_width * scr_height * 2;
scr_addr = as_get_mappable_page(sz);
395,6 → 396,6
}
 
 
/**
/**
* @}
*/
/branches/dynload/uspace/srv/fs/tmpfs/tmpfs.c
126,18 → 126,15
 
int main(int argc, char **argv)
{
int vfs_phone;
 
printf(NAME ": HelenOS TMPFS file system server\n");
 
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
while (vfs_phone < EOK) {
usleep(10000);
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
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");
return -1;
}
int rc;
rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
tmpfs_connection);
if (rc != EOK) {
printf(NAME ": Failed to register file system (%d)\n", rc);
/branches/dynload/uspace/srv/fs/fat/fat_dentry.h
73,13 → 73,13
union {
uint16_t eaidx; /* FAT12/FAT16 */
uint16_t firstc_hi; /* FAT32 */
};
} __attribute__ ((packed));
uint16_t mtime;
uint16_t mdate;
union {
uint16_t firstc; /* FAT12/FAT16 */
uint16_t firstc_lo; /* FAT32 */
};
} __attribute__ ((packed));
uint32_t size;
} __attribute__ ((packed)) fat_dentry_t;
 
/branches/dynload/uspace/srv/fs/fat/fat.c
128,10 → 128,10
if (rc != EOK)
goto err;
 
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
while (vfs_phone < EOK) {
usleep(10000);
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
if (vfs_phone < EOK) {
printf("fat: failed to connect to VFS\n");
return -1;
}
rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection);
/branches/dynload/uspace/srv/devmap/devmap.c
28,9 → 28,9
 
/**
* @defgroup devmap Device mapper.
* @brief HelenOS device mapper.
* @brief HelenOS device mapper.
* @{
*/
*/
 
/** @file
*/
46,17 → 46,24
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#define NAME "devmap"
 
/** Pending lookup structure. */
typedef struct {
link_t link;
char *name; /**< Device name */
ipc_callid_t callid; /**< Call ID waiting for the lookup */
} pending_req_t;
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(drivers_list);
LIST_INITIALIZE(pending_req);
 
/* order of locking:
* drivers_list_futex
* devices_list_futex
* (devmap_driver_t *)->devices_futex
* create_handle_futex
/* Locking order:
* drivers_list_futex
* devices_list_futex
* (devmap_driver_t *)->devices_futex
* create_handle_futex
**/
 
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
63,27 → 70,28
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
 
 
static int devmap_create_handle(void)
{
static int last_handle = 0;
int handle;
 
/* TODO: allow reusing old handles after their unregistration
and implement some version of LRU algorithm */
* and implement some version of LRU algorithm
*/
/* FIXME: overflow */
futex_down(&create_handle_futex);
 
futex_down(&create_handle_futex);
last_handle += 1;
handle = last_handle;
 
futex_up(&create_handle_futex);
 
futex_up(&create_handle_futex);
return handle;
}
 
 
/** Initialize device mapper.
/** Initialize device mapper.
*
*
*/
90,7 → 98,7
static int devmap_init()
{
/* TODO: */
 
return EOK;
}
 
99,108 → 107,101
*/
static devmap_device_t *devmap_device_find_name(const char *name)
{
link_t *item;
link_t *item = devices_list.next;
devmap_device_t *device = NULL;
 
item = devices_list.next;
 
while (item != &devices_list) {
 
device = list_get_instance(item, devmap_device_t, devices);
if (0 == strcmp(device->name, name)) {
if (0 == strcmp(device->name, name))
break;
}
item = item->next;
}
 
if (item == &devices_list)
return NULL;
 
device = list_get_instance(item, devmap_device_t, devices);
return device;
}
 
/** Find device with given handle.
*
* @todo: use hash table
*
*/
static devmap_device_t *devmap_device_find_handle(int handle)
{
link_t *item;
futex_down(&devices_list_futex);
link_t *item = (&devices_list)->next;
devmap_device_t *device = NULL;
futex_down(&devices_list_futex);
 
item = (&devices_list)->next;
 
while (item != &devices_list) {
 
device = list_get_instance(item, devmap_device_t, devices);
if (device->handle == handle) {
if (device->handle == handle)
break;
}
item = item->next;
}
 
if (item == &devices_list) {
futex_up(&devices_list_futex);
return NULL;
}
 
device = list_get_instance(item, devmap_device_t, devices);
futex_up(&devices_list_futex);
 
return device;
}
 
/**
*
* Unregister device and free it. It's assumed that driver's device list is
* already locked.
*
*/
static int devmap_device_unregister_core(devmap_device_t *device)
{
 
list_remove(&(device->devices));
list_remove(&(device->driver_devices));
 
free(device->name);
free(device->name);
free(device);
 
 
return EOK;
}
 
/**
*
* Read info about new driver and add it into linked list of registered
* drivers.
*
*/
static void devmap_driver_register(devmap_driver_t **odriver)
{
size_t name_size;
ipc_callid_t callid;
ipc_call_t call;
devmap_driver_t *driver;
ipc_callid_t iid;
ipc_call_t icall;
 
*odriver = NULL;
iid = async_get_call(&icall);
 
ipc_call_t icall;
ipc_callid_t iid = async_get_call(&icall);
if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (NULL ==
(driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) {
}
devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
if (driver == NULL) {
ipc_answer_0(iid, ENOMEM);
return;
}
 
/*
/*
* Get driver name
*/
ipc_callid_t callid;
size_t name_size;
if (!ipc_data_write_receive(&callid, &name_size)) {
free(driver);
ipc_answer_0(callid, EREFUSED);
207,7 → 208,7
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (name_size > DEVMAP_NAME_MAXLEN) {
free(driver);
ipc_answer_0(callid, EINVAL);
214,17 → 215,18
ipc_answer_0(iid, EREFUSED);
return;
}
 
/*
* Allocate buffer for device name.
*/
if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
driver->name = (char *) malloc(name_size + 1);
if (driver->name == NULL) {
free(driver);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
return;
}
 
}
/*
* Send confirmation to sender and get data into buffer.
*/
234,22 → 236,23
ipc_answer_0(iid, EREFUSED);
return;
}
 
driver->name[name_size] = 0;
 
/* Initialize futex for list of devices owned by this driver */
futex_initialize(&(driver->devices_futex), 1);
 
/*
/*
* Initialize list of asociated devices
*/
list_initialize(&(driver->devices));
 
/*
/*
* Create connection to the driver
*/
ipc_call_t call;
callid = async_get_call(&call);
 
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
ipc_answer_0(callid, ENOTSUP);
258,73 → 261,95
ipc_answer_0(iid, ENOTSUP);
return;
}
 
driver->phone = IPC_GET_ARG5(call);
ipc_answer_0(callid, EOK);
list_initialize(&(driver->drivers));
 
futex_down(&drivers_list_futex);
futex_down(&drivers_list_futex);
/* TODO:
* check that no driver with name equal to driver->name is registered
*/
 
/*
/*
* Insert new driver into list of registered drivers
*/
list_append(&(driver->drivers), &drivers_list);
futex_up(&drivers_list_futex);
futex_up(&drivers_list_futex);
ipc_answer_0(iid, EOK);
 
*odriver = driver;
}
 
/** Unregister device driver, unregister all its devices and free driver
/**
* Unregister device driver, unregister all its devices and free driver
* structure.
*
*/
static int devmap_driver_unregister(devmap_driver_t *driver)
{
devmap_device_t *device;
 
if (NULL == driver)
if (driver == NULL)
return EEXISTS;
futex_down(&drivers_list_futex);
 
futex_down(&drivers_list_futex);
ipc_hangup(driver->phone);
/* remove it from list of drivers */
list_remove(&(driver->drivers));
 
/* unregister all its devices */
futex_down(&devices_list_futex);
futex_down(&devices_list_futex);
futex_down(&(driver->devices_futex));
 
while (!list_empty(&(driver->devices))) {
device = list_get_instance(driver->devices.next,
devmap_device_t *device = list_get_instance(driver->devices.next,
devmap_device_t, driver_devices);
devmap_device_unregister_core(device);
}
futex_up(&(driver->devices_futex));
futex_up(&devices_list_futex);
futex_up(&drivers_list_futex);
 
futex_up(&devices_list_futex);
futex_up(&drivers_list_futex);
/* free name and driver */
if (NULL != driver->name) {
if (NULL != driver->name)
free(driver->name);
}
 
free(driver);
 
return EOK;
}
 
 
/** Process pending lookup requests */
static void process_pending_lookup()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
const devmap_device_t *dev = devmap_device_find_name(pr->name);
if (!dev)
continue;
ipc_answer_1(pr->callid, EOK, dev->handle);
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
 
 
/** Register instance of device
*
*/
331,29 → 356,27
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
devmap_driver_t *driver)
{
ipc_callid_t callid;
size_t size;
devmap_device_t *device;
 
if (NULL == driver) {
if (driver == NULL) {
ipc_answer_0(iid, EREFUSED);
return;
}
/* Create new device entry */
if (NULL ==
(device = (devmap_device_t *) malloc(sizeof(devmap_device_t)))) {
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL) {
ipc_answer_0(iid, ENOMEM);
return;
}
/* Get device name */
ipc_callid_t callid;
size_t size;
if (!ipc_data_write_receive(&callid, &size)) {
free(device);
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (size > DEVMAP_NAME_MAXLEN) {
free(device);
ipc_answer_0(callid, EINVAL);
363,8 → 386,8
/* +1 for terminating \0 */
device->name = (char *) malloc(size + 1);
 
if (NULL == device->name) {
if (device->name == NULL) {
free(device);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
373,12 → 396,12
ipc_data_write_finalize(callid, device->name, size);
device->name[size] = 0;
 
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
 
futex_down(&devices_list_futex);
 
futex_down(&devices_list_futex);
/* Check that device with such name is not already registered */
if (NULL != devmap_device_find_name(device->name)) {
printf(NAME ": Device '%s' already registered\n", device->name);
388,24 → 411,26
ipc_answer_0(iid, EEXISTS);
return;
}
 
/* Get unique device handle */
device->handle = devmap_create_handle();
 
device->handle = devmap_create_handle();
device->driver = driver;
/* Insert device into list of all devices */
list_append(&device->devices, &devices_list);
 
/* Insert device into list of devices that belog to one driver */
futex_down(&device->driver->devices_futex);
list_append(&device->driver_devices, &device->driver->devices);
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
 
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
ipc_answer_1(iid, EOK, device->handle);
process_pending_lookup();
}
 
/**
415,129 → 440,142
devmap_driver_t *driver)
{
/* TODO */
 
return EOK;
}
 
/** Connect client to the device.
*
* Find device driver owning requested device and forward
* the message to it.
*
*/
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
{
devmap_device_t *dev;
int handle;
 
/*
* Get handle from request
*/
handle = IPC_GET_ARG2(*call);
dev = devmap_device_find_handle(handle);
 
int handle = IPC_GET_ARG2(*call);
devmap_device_t *dev = devmap_device_find_handle(handle);
if (NULL == dev) {
ipc_answer_0(callid, ENOENT);
return;
}
 
}
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
}
 
/** Find handle for device instance identified by name.
*
* In answer will be send EOK and device handle in arg1 or a error
* code from errno.h.
* code from errno.h.
*
*/
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
{
char *name = NULL;
size_t name_size;
const devmap_device_t *dev;
ipc_callid_t callid;
ipcarg_t retval;
/*
/*
* Wait for incoming message with device name (but do not
* read the name itself until the buffer is allocated).
*/
if (!ipc_data_write_receive(&callid, &name_size)) {
ipc_callid_t callid;
size_t size;
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EREFUSED);
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (name_size > DEVMAP_NAME_MAXLEN) {
if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(iid, EREFUSED);
return;
}
 
/*
* Allocate buffer for device name.
*/
if (NULL == (name = (char *)malloc(name_size))) {
char *name = (char *) malloc(size);
if (name == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
return;
}
 
}
/*
* Send confirmation to sender and get data into buffer.
*/
if (EOK != (retval = ipc_data_write_finalize(callid, name,
name_size))) {
ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
if (retval != EOK) {
ipc_answer_0(iid, EREFUSED);
free(name);
return;
}
 
name[size] = '\0';
/*
* Find device name in linked list of known devices.
*/
dev = devmap_device_find_name(name);
 
const devmap_device_t *dev = devmap_device_find_name(name);
/*
* Device was not found.
*/
if (NULL == dev) {
if (dev == NULL) {
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
/* Blocking lookup, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(iid, ENOMEM);
free(name);
return;
}
pr->name = name;
pr->callid = iid;
list_append(&pr->link, &pending_req);
return;
}
ipc_answer_0(iid, ENOENT);
free(name);
return;
}
 
ipc_answer_1(iid, EOK, dev->handle);
free(name);
}
 
/** Find name of device identified by id and send it to caller.
/** Find name of device identified by id and send it to caller.
*
*/
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
{
const devmap_device_t *device;
size_t name_size;
 
device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
 
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
/*
* Device not found.
*/
if (NULL == device) {
if (device == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
 
}
ipc_answer_0(iid, EOK);
 
name_size = strlen(device->name);
 
 
/* FIXME:
we have no channel from DEVMAP to client ->
sending must be initiated by client
 
int rc = ipc_data_write_send(phone, device->name, name_size);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
*/
size_t name_size = strlen(device->name);
/* FIXME:
* We have no channel from DEVMAP to client, therefore
* sending must be initiated by client.
*
* int rc = ipc_data_write_send(phone, device->name, name_size);
* if (rc != EOK) {
* async_wait_for(req, NULL);
* return rc;
* }
*/
/* TODO: send name in response */
}
 
546,31 → 584,30
*/
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
bool cont = true;
/* Accept connection */
ipc_answer_0(iid, EOK);
devmap_driver_t *driver = NULL;
 
ipc_answer_0(iid, EOK);
 
devmap_driver_register(&driver);
 
if (NULL == driver)
return;
bool cont = true;
while (cont) {
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
continue; /* Exit thread */
/* Exit thread */
continue;
case DEVMAP_DRIVER_UNREGISTER:
if (NULL == driver) {
if (NULL == driver)
ipc_answer_0(callid, ENOENT);
} else {
else
ipc_answer_0(callid, EOK);
}
break;
case DEVMAP_DEVICE_REGISTER:
/* Register one instance of device */
587,20 → 624,18
devmap_get_handle(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION)) {
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, ENOENT);
}
}
}
if (NULL != driver) {
/*
/*
* Unregister the device driver and all its devices.
*/
devmap_driver_unregister(driver);
driver = NULL;
}
}
 
/** Handle connection with device client.
608,23 → 643,21
*/
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
/* Accept connection */
ipc_answer_0(iid, EOK);
bool cont = true;
 
ipc_answer_0(iid, EOK); /* Accept connection */
 
while (cont) {
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
continue; /* Exit thread */
 
/* Exit thread */
continue;
case DEVMAP_DEVICE_GET_HANDLE:
devmap_get_handle(callid, &call);
 
devmap_get_handle(callid, &call);
break;
case DEVMAP_DEVICE_GET_NAME:
/* TODO */
631,14 → 664,13
devmap_get_name(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION)) {
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, ENOENT);
}
}
}
}
 
/** Function for handling connections to devmap
/** Function for handling connections to devmap
*
*/
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
656,10 → 688,9
devmap_forward(iid, icall);
break;
default:
ipc_answer_0(iid, ENOENT); /* No such interface */
/* No such interface */
ipc_answer_0(iid, ENOENT);
}
 
/* Cleanup */
}
 
/**
669,8 → 700,6
{
printf(NAME ": HelenOS Device Mapper\n");
ipcarg_t phonead;
 
if (devmap_init() != 0) {
printf(NAME ": Error while initializing service\n");
return -1;
678,13 → 707,15
/* Set a handler of incomming connections */
async_set_client_connection(devmap_connection);
 
/* Register device mapper at naming service */
ipcarg_t phonead;
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
/* Never reached */
return 0;
}
/branches/dynload/uspace/srv/vfs/vfs.c
28,11 → 28,11
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs.c
* @brief VFS service for HelenOS.
* @file vfs.c
* @brief VFS service for HelenOS.
*/
 
#include <ipc/ipc.h>
51,14 → 51,14
 
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = 1;
 
bool keep_on_going = true;
/*
* The connection was opened via the IPC_CONNECT_ME_TO call.
* This call needs to be answered.
*/
ipc_answer_0(iid, EOK);
 
/*
* Here we enter the main connection fibril loop.
* The logic behind this loop and the protocol is that we'd like to keep
70,13 → 70,12
* connection later.
*/
while (keep_on_going) {
ipc_callid_t callid;
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
fs_handle_t fs_handle;
int phone;
fs_handle_t fs_handle;
 
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
keep_on_going = false;
139,22 → 138,19
break;
}
}
 
/* TODO: cleanup after the client */
}
 
int main(int argc, char **argv)
{
ipcarg_t phonead;
 
printf(NAME ": HelenOS VFS server\n");
 
/*
* Initialize the list of registered file systems.
*/
list_initialize(&fs_head);
 
/*
* Initialize VFS node hash table.
*/
162,7 → 158,7
printf(NAME ": Failed to initialize VFS node hash table\n");
return ENOMEM;
}
 
/*
* Allocate and initialize the Path Lookup Buffer.
*/
172,6 → 168,7
printf(NAME ": Cannot allocate a mappable piece of address space\n");
return ENOMEM;
}
if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE |
AS_AREA_CACHEABLE) != plb) {
printf(NAME ": Cannot create address space area\n");
183,12 → 180,13
* Set a connectio handling function/fibril.
*/
async_set_client_connection(vfs_connection);
 
/*
* Register at the naming service.
*/
ipcarg_t phonead;
ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, 0, &phonead);
 
/*
* Start accepting connections.
*/
199,4 → 197,4
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/vfs/vfs_ops.c
28,11 → 28,11
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs_ops.c
* @brief Operations that VFS offers to its clients.
* @file vfs_ops.c
* @brief Operations that VFS offers to its clients.
*/
 
#include "vfs.h"
55,6 → 55,18
/* Forward declarations of static functions. */
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
 
/** Pending mount structure. */
typedef struct {
link_t link;
char *fs_name; /**< File system name */
char *mp; /**< Mount point */
ipc_callid_t callid; /**< Call ID waiting for the mount */
ipc_callid_t rid; /**< Request ID */
dev_handle_t dev_handle; /**< Device handle */
} pending_req_t;
 
LIST_INITIALIZE(pending_req);
 
/**
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a
* concurrent VFS operation which modifies the file system namespace.
67,135 → 79,43
.dev_handle = 0
};
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle,
fs_handle_t fs_handle, char *mp)
{
dev_handle_t dev_handle;
/* Resolve the path to the mountpoint. */
vfs_lookup_res_t mp_res;
vfs_node_t *mp_node = NULL;
ipc_callid_t callid;
ipc_call_t data;
int rc;
int phone;
size_t size;
 
/*
* We expect the library to do the device-name to device-handle
* translation for us, thus the device handle will arrive as ARG1
* in the request.
*/
dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
 
/*
* For now, don't make use of ARG2 and ARG3, but they can be used to
* carry mount options in the future.
*/
 
/*
* Now, we expect the client to send us data with the name of the file
* system.
*/
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
/*
* Don't receive more than is necessary for storing a full file system
* name.
*/
if (size < 1 || size > FS_NAME_MAXLEN) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
/* Deliver the file system name. */
char fs_name[FS_NAME_MAXLEN + 1];
(void) ipc_data_write_finalize(callid, fs_name, size);
fs_name[size] = '\0';
/*
* Wait for IPC_M_PING so that we can return an error if we don't know
* fs_name.
*/
callid = async_get_call(&data);
if (IPC_GET_METHOD(data) != IPC_M_PING) {
ipc_answer_0(callid, ENOTSUP);
ipc_answer_0(rid, ENOTSUP);
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.
*/
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
 
/* Now, we want the client to send us the mount point. */
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
/* Check whether size is reasonable wrt. the mount point. */
if (size < 1 || size > MAX_PATH_LEN) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
/* Allocate buffer for the mount point data being received. */
char *buf;
buf = malloc(size + 1);
if (!buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
/* Deliver the mount point. */
(void) ipc_data_write_finalize(callid, buf, size);
buf[size] = '\0';
 
/* Resolve the path to the mountpoint. */
vfs_lookup_res_t mp_res;
futex_down(&rootfs_futex);
if (rootfs.fs_handle) {
/* We already have the root FS. */
rwlock_write_lock(&namespace_rwlock);
if ((size == 1) && (buf[0] == '/')) {
if ((strlen(mp) == 1) && (mp[0] == '/')) {
/* Trying to mount root FS over root FS */
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, EBUSY);
return;
}
rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL);
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
if (rc != EOK) {
/* The lookup failed for some reason. */
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, rc);
return;
}
mp_node = vfs_node_get(&mp_res);
if (!mp_node) {
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* Now we hold a reference to mp_node.
* It will be dropped upon the corresponding VFS_UNMOUNT.
204,18 → 124,17
rwlock_write_unlock(&namespace_rwlock);
} else {
/* We still don't have the root file system mounted. */
if ((size == 1) && (buf[0] == '/')) {
if ((strlen(mp) == 1) && (mp[0] == '/')) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
ipcarg_t rindex;
ipcarg_t rsize;
ipcarg_t rlnkcnt;
/*
* For this simple, but important case,
* we are almost done.
*/
free(buf);
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
228,7 → 147,7
ipc_answer_0(rid, rc);
return;
}
 
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = (fs_index_t) rindex;
235,15 → 154,15
mr_res.size = (size_t) rsize;
mr_res.lnkcnt = (unsigned) rlnkcnt;
mr_res.type = VFS_NODE_DIRECTORY;
 
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
futex_up(&rootfs_futex);
 
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
 
ipc_answer_0(rid, rc);
return;
} else {
252,7 → 171,6
* being mounted first.
*/
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, ENOENT);
return;
}
259,13 → 177,11
}
futex_up(&rootfs_futex);
free(buf); /* The buffer is not needed anymore. */
/*
* At this point, we have all necessary pieces: file system and device
* handles, and we know the mount point VFS node.
*/
 
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
rc = async_req_4_0(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
273,7 → 189,7
(ipcarg_t) fs_handle,
(ipcarg_t) dev_handle);
vfs_release_phone(phone);
 
if (rc != EOK) {
/* Mount failed, drop reference to mp_node. */
if (mp_node)
283,6 → 199,170
ipc_answer_0(rid, rc);
}
 
/** Process pending mount requests */
void vfs_process_pending_mount()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
if (!fs_handle)
continue;
/* Acknowledge that we know fs_name. */
ipc_answer_0(pr->callid, EOK);
/* Do the mount */
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp);
free(pr->fs_name);
free(pr->mp);
list_remove(cur);
free(pr);
goto loop;
}
}
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
/*
* We expect the library to do the device-name to device-handle
* translation for us, thus the device handle will arrive as ARG1
* in the request.
*/
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
/*
* Mount flags are passed as ARG2.
*/
unsigned int flags = (unsigned int) IPC_GET_ARG2(*request);
/*
* For now, don't make use of ARG3, but it can be used to
* carry mount options in the future.
*/
/* We want the client to send us the mount point. */
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;
}
/* Check whether size is reasonable wrt. the mount point. */
if ((size < 1) || (size > MAX_PATH_LEN)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
/* Allocate buffer for the mount point data being received. */
char *mp = malloc(size + 1);
if (!mp) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
/* Deliver the mount point. */
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size);
if (retval != EOK) {
ipc_answer_0(rid, EREFUSED);
free(mp);
return;
}
mp[size] = '\0';
/*
* Now, we expect the client to send us data with the name of the file
* system.
*/
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
return;
}
/*
* Don't receive more than is necessary for storing a full file system
* name.
*/
if ((size < 1) || (size > FS_NAME_MAXLEN)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
return;
}
/*
* Allocate buffer for file system name.
*/
char *fs_name = (char *) malloc(size + 1);
if (fs_name == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, EREFUSED);
free(mp);
return;
}
/* Deliver the file system name. */
retval = ipc_data_write_finalize(callid, fs_name, size);
if (retval != EOK) {
ipc_answer_0(rid, EREFUSED);
free(mp);
free(fs_name);
return;
}
fs_name[size] = '\0';
/*
* 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.
*/
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
if (flags & IPC_FLAG_BLOCKING) {
/* Blocking mount, add to pending list */
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);
return;
}
pr->fs_name = fs_name;
pr->mp = mp;
pr->callid = callid;
pr->rid = rid;
pr->dev_handle = dev_handle;
list_append(&pr->link, &pending_req);
return;
}
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
free(mp);
free(fs_name);
return;
}
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
/* Do the mount */
vfs_mount_internal(rid, dev_handle, fs_handle, mp);
free(mp);
free(fs_name);
}
 
void vfs_open(ipc_callid_t rid, ipc_call_t *request)
{
if (!vfs_files_init()) {
/branches/dynload/uspace/srv/vfs/vfs_register.c
28,10 → 28,10
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs_register.c
* @file vfs_register.c
* @brief
*/
 
278,6 → 278,11
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
/* Process pending mount requests possibly waiting
* for this filesystem implementation.
*/
vfs_process_pending_mount();
}
 
/** For a given file system handle, implement policy for allocating a phone.
/branches/dynload/uspace/srv/vfs/vfs.h
282,6 → 282,7
extern void vfs_node_addref(vfs_node_t *);
extern void vfs_node_delref(vfs_node_t *);
 
extern void vfs_process_pending_mount(void);
extern void vfs_register(ipc_callid_t, ipc_call_t *);
extern void vfs_mount(ipc_callid_t, ipc_call_t *);
extern void vfs_open(ipc_callid_t, ipc_call_t *);