/*
* Copyright (c) 2005 Martin Decky
* Copyright (c) 2008 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ipc/ipc.h>
#include <syscall.h>
#include <libc.h>
#include <console.h>
#include <ipc/services.h>
#include <vfs/vfs.h>
#include <errno.h>
#include <fcntl.h>
#include "../../srv/vfs/vfs.h"
static void kputint(unsigned i)
{
unsigned dummy;
asm volatile (
"movl $30, %%eax;"
"int $0x30"
: "=d" (dummy) /* output - %edx clobbered */
: "d" (i) /* input */
: "%eax","%ecx" /* all scratch registers clobbered */
);
}
int
ipc_call_sync_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3,
ipcarg_t *result4, ipcarg_t *result5)
{
ipc_call_t resdata;
int callres;
callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
arg2, arg3, (sysarg_t) &resdata);
if (callres)
return callres;
if (result1)
*result1 = IPC_GET_ARG1(resdata);
if (result2)
*result2 = IPC_GET_ARG2(resdata);
if (result3)
*result3 = IPC_GET_ARG3(resdata);
if (result4)
*result4 = IPC_GET_ARG4(resdata);
if (result5)
*result5 = IPC_GET_ARG5(resdata);
return IPC_GET_RETVAL(resdata);
}
int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3)
{
ipcarg_t newphid;
int res;
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
NULL, NULL, NULL, NULL, &newphid);
if (res)
return res;
return newphid;
}
ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
{
ipc_callid_t callid;
callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
return callid;
}
ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
{
ipc_callid_t callid;
callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
return callid;
}
ipc_callid_t ipc_purge_answers(void)
{
ipc_callid_t callid;
ipc_call_t call;
do {
callid = ipc_wait_cycle(&call, 0, SYNCH_FLAGS_NON_BLOCKING);
printf("ipc_wait_cycle->%d\n", callid
);
} while (callid != 0);
return callid;
}
ipc_callid_t ipc_wait_for_answer(ipc_callid_t req, ipc_call_t *call)
{
ipc_callid_t callid;
do {
callid = ipc_wait_cycle(call, 0, SYNCH_FLAGS_NONE);
} while ((callid & ~IPC_CALLID_ANSWERED) != req);
return callid;
}
static ipc_callid_t async_rid;
void ipc_call_async_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, void *private,
ipc_async_callback_t callback, int can_preempt)
{
ipc_purge_answers();
async_rid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1,
arg2, arg3, arg4);
printf("ipc_call_async_fast->%d\n", async_rid
);
}
int ipc_data_write_start(int phoneid, void *src, size_t size)
{
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
(ipcarg_t) size);
}
int ipc_data_read_start(int phoneid, void *dst, size_t size)
{
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
(ipcarg_t) size);
}
static int console_phone = -1;
ssize_t write_stderr(const void *buf, size_t count)
{
return count;
}
ssize_t read_stdin(void *buf, size_t count)
{
ipcarg_t r0, r1;
size_t i = 0;
while (i < count) {
if (ipc_call_sync_0_2(console_phone, CONSOLE_GETCHAR, &r0,
&r1) < 0) {
return -1;
}
((char *) buf)[i++] = r0;
}
return i;
}
ssize_t write_stdout(const void *buf, size_t count)
{
int i;
for (i = 0; i < count; i++)
ipc_call_sync_1_0(console_phone, CONSOLE_PUTCHAR,
((const char *) buf)[i]);
return count;
}
void open_stdin(void)
{
kputint(0x1234);
if (console_phone < 0) {
while ((console_phone = ipc_connect_me_to(PHONE_NS,
SERVICE_CONSOLE, 0, 0)) < 0) {
//usleep(10000);
}
kputint(console_phone);
}
}
void open_stdout(void)
{
kputint(0x1235);
if (console_phone < 0) {
while ((console_phone = ipc_connect_me_to(PHONE_NS,
SERVICE_CONSOLE, 0, 0)) < 0) {
//usleep(10000);
}
kputint(console_phone);
}
}
int get_cons_phone(void)
{
return console_phone;
}
void __main(void)
{
kputint(0x110);
}
void __io_init(void)
{
open_stdin();
open_stdout();
}
void __exit(void)
{
kputint(0x112);
}
{
unsigned char ch = c;
if (write_stdout((void *) &ch, 1) == 1)
return c;
return EOF;
}
{
unsigned char c;
if (read_stdin((void *) &c, 1) == 1)
return c;
return EOF;
}
void _putint(int i)
{
if (i == 0) {
return;
}
if (i < 0) {
i = -i;
}
if (i >= 10) {
_putint(i/10);
}
}
int printf(const char *fmt
, ...
)
{
int c;
int i;
va_list ap;
while (*fmt) {
c = *fmt++;
if (c == '%') {
c = *fmt++;
if (c == 'd') {
_putint(i);
} else if (c == '\0') {
break;
} else {
}
} else {
}
}
return 0;
}
{
int l = 0;
while (*s) { ++s; ++l; }
return l;
}
//int vfs_phone = -1;
int vfs_phone = 2; /* reuse phone from loader */
static int vfs_connect(void)
{
if (vfs_phone < 0)
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
return vfs_phone;
}
static int _open(const char *path, int lflag, int oflag, ...)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
const char *pa = path;
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
return res;
}
}
ipc_call_async_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, NULL, NULL,0);
rc = ipc_data_write_start(vfs_phone, (char *)pa, pa_len);
if (rc != EOK) {
ipc_wait_for_answer(async_rid, &answer);
return (int) rc;
}
ipc_wait_for_answer(async_rid, &answer);
return (int) IPC_GET_ARG1(answer);
}
int open(const char *path, int oflag, ...)
{
return _open(path, L_FILE, oflag);
}
int close(int fildes)
{
int res;
ipcarg_t rc;
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
return res;
}
}
rc = ipc_call_sync_1_0(vfs_phone, VFS_CLOSE, fildes);
return (int)rc;
}
ssize_t read(int fildes, void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
return res;
}
}
ipc_call_async_1(vfs_phone, VFS_READ, fildes, NULL, NULL, 0);
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
ipc_wait_for_answer(async_rid, &answer);
return (ssize_t) rc;
}
ipc_wait_for_call(&answer);
if (rc == EOK)
return (ssize_t) IPC_GET_ARG1(answer);
else
return -1;
}