Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3664 → Rev 3665

/branches/sparc/uspace/app/bdsh/cmds/modules/cp/cp.c
30,6 → 30,11
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "config.h"
#include "util.h"
#include "errors.h"
37,37 → 42,183
#include "cp.h"
#include "cmds.h"
 
static char *cmdname = "cp";
#define CP_VERSION "0.0.1"
#define CP_DEFAULT_BUFLEN 1024
 
/* Dispays help for cp in various levels */
static const char *cmdname = "cp";
 
static struct option const long_options[] = {
{ "buffer", required_argument, 0, 'b' },
{ "force", no_argument, 0, 'f' },
{ "recursive", no_argument, 0, 'r' },
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "verbose", no_argument, 0, 'V' },
{ 0, 0, 0, 0 }
};
 
static int strtoint(const char *s1)
{
long t1;
 
if (-1 == (t1 = strtol(s1, (char **) NULL, 10)))
return -1;
 
if (t1 <= 0)
return -1;
 
return (int) t1;
}
 
static int64_t copy_file(const char *src, const char *dest, size_t blen, int vb)
{
int fd1, fd2, bytes = 0;
off_t total = 0;
int64_t copied = 0;
char *buff = NULL;
 
if (vb)
printf("Copying %s to %s\n", src, dest);
 
if (-1 == (fd1 = open(src, O_RDONLY))) {
printf("Unable to open source file %s\n", src);
return -1;
}
 
if (-1 == (fd2 = open(dest, O_CREAT))) {
printf("Unable to open destination file %s\n", dest);
close(fd1);
return -1;
}
 
total = lseek(fd1, 0, SEEK_END);
 
if (vb)
printf("%d bytes to copy\n", total);
 
lseek(fd1, 0, SEEK_SET);
 
if (NULL == (buff = (char *) malloc(blen))) {
printf("Unable to allocate enough memory to read %s\n",
src);
copied = -1;
goto out;
}
 
for (;;) {
ssize_t res;
 
bytes = read(fd1, buff, blen);
if (bytes <= 0)
break;
copied += bytes;
res = bytes;
do {
/*
* Theoretically, it may not be enough to call write()
* only once. Also the previous read() may have
* returned less data than requested.
*/
bytes = write(fd2, buff, res);
if (bytes < 0)
goto err;
res -= bytes;
} while (res > 0);
assert(res == 0);
}
 
if (bytes < 0) {
err:
printf("Error copying %s, (%d)\n", src, bytes);
copied = bytes;
}
 
out:
close(fd1);
close(fd2);
if (buff)
free(buff);
return copied;
}
 
void help_cmd_cp(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
static char helpfmt[] =
"Usage: %s [options] <source> <dest>\n"
"Options: (* indicates not yet implemented)\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
"* -V, --verbose Be annoyingly noisy about what's being done\n"
"* -f, --force Do not complain when <dest> exists\n"
"* -r, --recursive Copy entire directories\n"
" -b, --buffer ## Set the read buffer size to ##\n"
"Currently, %s is under development, some options may not work.\n";
if (level == HELP_SHORT) {
printf("`%s' copies files and directories\n", cmdname);
} else {
help_cmd_cp(HELP_SHORT);
printf(helpfmt, cmdname, cmdname);
}
 
return;
}
 
/* Main entry point for cp, accepts an array of arguments */
int cmd_cp(char **argv)
{
unsigned int argc;
unsigned int i;
unsigned int argc, buffer = 0, verbose = 0;
int c, opt_ind;
int64_t ret;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
argc = cli_count_args(argv);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_cp(1);
return CMD_SUCCESS;
case 'v':
printf("%d\n", CP_VERSION);
return CMD_SUCCESS;
case 'V':
verbose = 1;
break;
case 'f':
break;
case 'r':
break;
case 'b':
if (-1 == (buffer = strtoint(optarg))) {
printf("%s: Invalid buffer specification, "
"(should be a number greater than zero)\n",
cmdname);
return CMD_FAILURE;
}
if (verbose)
printf("Buffer = %d\n", buffer);
break;
}
}
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
if (buffer == 0)
buffer = CP_DEFAULT_BUFLEN;
 
argc -= optind;
 
if (argc != 2) {
printf("%s: invalid number of arguments. Try %s --help\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose);
 
return CMD_SUCCESS;
if (verbose)
printf("%d bytes copied\n", ret);
 
if (ret >= 0)
return CMD_SUCCESS;
else
return CMD_FAILURE;
}
 
/branches/sparc/uspace/app/tester/tester.c
56,6 → 56,7
#include "ipc/answer.def"
#include "ipc/hangup.def"
#include "devmap/devmap1.def"
#include "loop/loop1.def"
#include "vfs/vfs1.def"
{NULL, NULL, NULL}
};
/branches/sparc/uspace/app/tester/loop/loop1.def
0,0 → 1,6
{
"loop1",
"Endless loop",
&test_loop1,
false
},
/branches/sparc/uspace/app/tester/loop/loop1.c
0,0 → 1,41
/*
* 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 "../tester.h"
 
char *test_loop1(bool quiet)
{
printf("Looping...\n");
while (1);
printf("Survived endless loop?!!\n");
 
return NULL;
}
 
/branches/sparc/uspace/app/tester/tester.h
69,6 → 69,7
extern char * test_answer(bool quiet);
extern char * test_hangup(bool quiet);
extern char * test_devmap1(bool quiet);
extern char * test_loop1(bool quiet);
extern char * test_vfs1(bool quiet);
 
extern test_t tests[];
/branches/sparc/uspace/app/tester/Makefile
54,6 → 54,7
ipc/send_sync.c \
ipc/answer.c \
ipc/hangup.c \
loop/loop1.c \
devmap/devmap1.c \
vfs/vfs1.c
 
/branches/sparc/uspace/app/trace/trace.c
445,10 → 445,20
thread_hash = (uintptr_t)thread_hash_arg;
thread_id = next_thread_id++;
 
printf("Start tracing thread [%d] (hash 0x%lx)\n", thread_id, thread_hash);
printf("Start tracing thread [%d] (hash 0x%lx).\n", thread_id, thread_hash);
 
while (!abort_trace) {
 
if (paused) {
printf("Press R to resume (and be patient).\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("Resumed\n");
}
 
/* Run thread until an event occurs */
rc = udebug_go(phoneid, thread_hash,
&ev_type, &val0, &val1);
469,23 → 479,16
break;
case UDEBUG_EVENT_STOP:
printf("Stop event\n");
printf("Waiting for resume\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("Resumed\n");
break;
case UDEBUG_EVENT_THREAD_B:
event_thread_b(val0);
break;
case UDEBUG_EVENT_THREAD_E:
printf("Thread 0x%lx exited\n", val0);
printf("Thread 0x%lx exited.\n", val0);
abort_trace = 1;
break;
default:
printf("Unknown event type %d\n", ev_type);
printf("Unknown event type %d.\n", ev_type);
break;
}
}
492,7 → 495,7
 
}
 
printf("Finished tracing thread [%d]\n", thread_id);
printf("Finished tracing thread [%d].\n", thread_id);
return 0;
}
 
580,6 → 583,7
c = getchar();
if (c == 'q') break;
if (c == 'p') {
printf("Pause...\n");
paused = 1;
rc = udebug_stop(phoneid, thash);
printf("stop -> %d\n", rc);
586,6 → 590,7
}
if (c == 'r') {
paused = 0;
printf("Resume...\n");
}
}
 
702,7 → 707,7
case 'i': dm = dm | DM_IPC; break;
case 'p': dm = dm | DM_SYSTEM | DM_USER; break;
default:
printf("Unexpected event type '%c'\n", *c);
printf("Unexpected event type '%c'.\n", *c);
exit(1);
}
 
777,6 → 782,7
int rc;
 
printf("System Call / IPC Tracer\n");
printf("Controls: Q - Quit, P - Pause, R - Resume\n");
 
display_mask = DM_THREAD | DM_SYSTEM | DM_USER;
 
787,11 → 793,11
 
rc = connect_task(task_id);
if (rc < 0) {
printf("Failed connecting to task %lld\n", task_id);
printf("Failed connecting to task %lld.\n", task_id);
return 1;
}
 
printf("Connected to task %lld\n", task_id);
printf("Connected to task %lld.\n", task_id);
 
if (task_ldr != NULL) {
program_run();
/branches/sparc/uspace/dist/readme
0,0 → 1,0
Lorem ipsum.
/branches/sparc/uspace/lib/libfs/libfs.c
196,12 → 196,15
nodep = ops->node_get(dev_handle,
index);
if (nodep) {
if (!ops->link(cur, nodep, component)) {
int rc;
 
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE) {
(void)ops->destroy(
nodep);
}
ipc_answer_0(rid, ENOSPC);
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
266,10 → 269,13
else
nodep = ops->node_get(dev_handle, index);
if (nodep) {
if (!ops->link(cur, nodep, component)) {
int rc;
 
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE)
(void)ops->destroy(nodep);
ipc_answer_0(rid, ENOSPC);
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
/branches/sparc/uspace/lib/libfs/libfs.h
47,7 → 47,7
void (* node_put)(void *);
void * (* create)(dev_handle_t, int);
int (* destroy)(void *);
bool (* link)(void *, void *, const char *);
int (* link)(void *, void *, const char *);
int (* unlink)(void *, void *);
fs_index_t (* index_get)(void *);
size_t (* size_get)(void *);
/branches/sparc/uspace/lib/libc/include/ctype.h
79,11 → 79,19
static inline int tolower(int c)
{
if (isupper(c))
return (c + ('a' - 'A' > 0 ? 'a' - 'A' : 'A' - 'a'));
return (c + ('a' - 'A'));
else
return c;
}
 
static inline int toupper(int c)
{
if (islower(c))
return (c + ('A' - 'a'));
else
return c;
}
 
#endif
 
/** @}
/branches/sparc/uspace/lib/libc/include/ipc/loader.h
44,7 → 44,7
LOADER_SET_ARGS,
LOADER_LOAD,
LOADER_RUN
} fb_request_t;
} loader_request_t;
 
#endif
 
/branches/sparc/uspace/lib/libc/include/errno.h
47,6 → 47,7
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#endif
 
/branches/sparc/uspace/lib/libc/arch/ia64/include/ddi.h
0,0 → 1,98
/*
* Copyright (c) 2005 Jakub Jermar, Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64
* @{
*/
/** @file
*/
 
#ifndef LIBC_ia64_DDI_H_
#define LIBC_ia64_DDI_H_
 
#include <libarch/types.h>
 
typedef uint64_t ioport_t;
 
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()))
 
static inline void outb(ioport_t port,uint8_t v)
{
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outw(ioport_t port,uint16_t v)
{
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outl(ioport_t port,uint32_t v)
{
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
 
 
static inline uint8_t inb(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
static inline uint16_t inw(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 ))));
}
 
static inline uint32_t inl(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
 
 
 
#endif
 
/** @}
*/
/branches/sparc/uspace/lib/libc/arch/ia64/Makefile.inc
41,7 → 41,8
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
arch/$(ARCH)/src/tls.c\
arch/$(ARCH)/src/ddi.c
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64-elf64
/branches/sparc/uspace/lib/libc/arch/ia64/src/ddi.c
0,0 → 1,13
#include <libarch/ddi.h>
#include <sysinfo.h>
 
uint64_t ia64_iospace_address=0;
 
 
uint64_t get_ia64_iospace_address(void)
{
 
return sysinfo_value("ia64_iospace.address.virtual");
 
}
 
/branches/sparc/uspace/srv/kbd/Makefile
59,6 → 59,15
genarch/src/kbd.c
CFLAGS += -DMOUSE_ENABLED
endif
ifeq ($(ARCH), ia64)
ARCH_SOURCES += \
arch/$(ARCH)/src/mouse.c \
arch/$(ARCH)/src/scanc.c \
arch/$(ARCH)/src/lkbd.c
GENARCH_SOURCES = \
genarch/src/kbd.c
CFLAGS += -DMOUSE_ENABLED
endif
ifeq ($(ARCH), amd64)
ARCH_SOURCES += \
arch/$(ARCH)/src/mouse.c \
/branches/sparc/uspace/srv/kbd/arch/ia64/include/lkbd.h
0,0 → 1,76
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdamd64 amd64
* @brief HelenOS ia32 / amd64 arch dependent parts of uspace keyboard and mouse handler.
* @ingroup kbd
* @{
*/
 
/** @file
* @ingroup kbdia32
*/
 
#ifndef KBD_ia32_KBD_H_
#define KBD_ia32_KBD_H_
 
#include <ddi.h>
#include <libarch/ddi.h>
 
#define i8042_DATA 0x60
#define i8042_STATUS 0X64
 
 
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/sparc/uspace/srv/kbd/arch/ia64/include/scanc.h
0,0 → 1,59
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdia32
* @{
*/
/** @file
* @ingroup kbdamd64
*/
 
#ifndef KBD_ia32_SCANC_H_
#define KBD_ia32_SCANC_H_
 
/** Scancodes. */
#define SC_ESC 0x01
#define SC_BACKSPACE 0x0e
#define SC_LSHIFT 0x2a
#define SC_RSHIFT 0x36
#define SC_CAPSLOCK 0x3a
#define SC_SPEC_ESCAPE 0xe0
#define SC_LEFTARR 0x4b
#define SC_RIGHTARR 0x4d
#define SC_UPARR 0x48
#define SC_DOWNARR 0x50
#define SC_DELETE 0x53
#define SC_HOME 0x47
#define SC_END 0x4f
 
#endif
 
/**
* @}
*/
/branches/sparc/uspace/srv/kbd/arch/ia64/src/kbd.c
39,7 → 39,30
#include <sysinfo.h>
#include <kbd.h>
#include <keys.h>
#include <stdio.h>
#include <stdlib.h>
 
#include <unistd.h>
#include <align.h>
#include <async.h>
#include <ipc/ipc.h>
#include <errno.h>
#include <stdio.h>
#include <ddi.h>
#include <sysinfo.h>
#include <as.h>
#include <ipc/fb.h>
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/services.h>
#include <libarch/ddi.h>
 
 
extern int lkbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call);
extern int lkbd_arch_init(void);
 
 
 
#define KEY_F1 0x504f1b
#define KEY_F2 0x514f1b
#define KEY_F3 0x524f1b
53,8 → 76,45
#define KEY_F11 0x7e33325b1b
#define KEY_F12 0x7e34325b1b
 
 
 
 
#define NSKEY_F1 0x415b5b1b
#define NSKEY_F2 0x425b5b1b
#define NSKEY_F3 0x435b5b1b
#define NSKEY_F4 0x445b5b1b
#define NSKEY_F5 0x455b5b1b
#define NSKEY_F6 0x37315b1b
#define NSKEY_F7 0x38315b1b
#define NSKEY_F8 0x39315b1b
#define NSKEY_F9 0x30325b1b
#define NSKEY_F10 0x31325b1b
#define NSKEY_F11 0x33325b1b
#define NSKEY_F12 0x34325b1b
 
 
#define FUNCTION_KEYS 0x100
 
 
#define KBD_SKI 1
#define KBD_LEGACY 2
#define KBD_NS16550 3
 
 
 
 
/* NS16550 registers */
#define RBR_REG 0 /** Receiver Buffer Register. */
#define IER_REG 1 /** Interrupt Enable Register. */
#define IIR_REG 2 /** Interrupt Ident Register (read). */
#define FCR_REG 2 /** FIFO control register (write). */
#define LCR_REG 3 /** Line Control register. */
#define MCR_REG 4 /** Modem Control Register. */
#define LSR_REG 5 /** Line Status Register. */
 
 
 
 
irq_cmd_t ski_cmds[1] = {
{ CMD_IA64_GETCHAR, 0, 0, 2 }
};
64,10 → 124,33
ski_cmds
};
 
 
 
irq_cmd_t ns16550_cmds[1] = {
{ CMD_PORT_READ_1, 0, 0, 2 },
};
 
irq_code_t ns16550_kbd = {
1,
ns16550_cmds
};
 
 
uint16_t ns16550_port;
 
int kbd_type;
 
int kbd_arch_init(void)
{
if (sysinfo_value("kbd")) {
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ski_kbd);
kbd_type=sysinfo_value("kbd.type");
if(kbd_type==KBD_SKI) ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ski_kbd);
if(kbd_type==KBD_LEGACY) return lkbd_arch_init();
if(kbd_type==KBD_NS16550) {
ns16550_kbd.cmds[0].addr= (void *) (sysinfo_value("kbd.port")+RBR_REG);
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ns16550_kbd);
iospace_enable(task_get_id(),ns16550_port=sysinfo_value("kbd.port"),8);
}
return 0;
}
return 1;
81,14 → 164,163
return "0123456789ABCDEF"[v];
}
*/
#define LSR_DATA_READY 0x01
 
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
int kbd_ns16550_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
static unsigned long buf = 0;
static int count = 0, esc_count=0;
 
int scan_code = IPC_GET_ARG2(*call);
 
if (scan_code == 0x1b) {
esc_count++;
if (esc_count == 3) {
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
}
} else {
esc_count = 0;
}
 
if(scan_code==0x0d) return 1; //Delete CR
if(scan_code==0x7f) scan_code='\b'; //Convert backspace
 
if(scan_code == 0x7e) {
switch (buf) {
case NSKEY_F6:
keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
buf = count = 0;
return 1;
case NSKEY_F7:
keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
buf = count = 0;
return 1;
case NSKEY_F8:
keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
buf = count = 0;
return 1;
case NSKEY_F9:
keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
buf = count = 0;
return 1;
case NSKEY_F10:
keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
buf = count = 0;
return 1;
case NSKEY_F11:
keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
buf = count = 0;
return 1;
case NSKEY_F12:
keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
buf = count = 0;
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
keybuffer_push(keybuffer, scan_code);
buf = count = 0;
return 1;
}
}
 
buf |= ((unsigned long) scan_code)<<(8*(count++));
if((buf & 0xff) != (NSKEY_F1 & 0xff)) {
keybuffer_push(keybuffer, buf);
buf = count = 0;
return 1;
}
 
if (count <= 1)
return 1;
 
if ((buf & 0xffff) != (NSKEY_F1 & 0xffff)) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 2)
return 1;
 
 
if ((buf & 0xffffff) != (NSKEY_F1 & 0xffffff)
&& (buf & 0xffffff) != (NSKEY_F6 & 0xffffff)
&& (buf & 0xffffff) != (NSKEY_F9 & 0xffffff) ) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 3)
return 1;
 
switch (buf) {
case NSKEY_F1:
keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
buf = count = 0;
return 1;
case NSKEY_F2:
keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
buf = count = 0;
return 1;
case NSKEY_F3:
keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
buf = count = 0;
return 1;
case NSKEY_F4:
keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
buf = count = 0;
return 1;
case NSKEY_F5:
keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
buf = count = 0;
return 1;
}
 
 
switch (buf) {
case NSKEY_F6:
case NSKEY_F7:
case NSKEY_F8:
case NSKEY_F9:
case NSKEY_F10:
case NSKEY_F11:
case NSKEY_F12:
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
buf = count = 0;
return 1;
}
return 1;
}
 
 
 
 
 
 
 
int kbd_ski_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
static unsigned long long buf = 0;
static int count = 0;
static int esc_count = 0;
int scan_code = IPC_GET_ARG2(*call);
 
/*
* Please preserve this code (it can be used to determine scancodes)
*/
155,10 → 387,21
}
buf = count = 0;
}
 
return 1;
}
 
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
printf("KBD Key pressed: %x(%c)\n",IPC_GET_ARG2(*call),IPC_GET_ARG2(*call));
if(kbd_type==KBD_SKI) return kbd_ski_process(keybuffer,call);
if(kbd_type==KBD_NS16550) return kbd_ns16550_process(keybuffer,call);
if(kbd_type==KBD_LEGACY) return lkbd_arch_process(keybuffer,call);
 
}
 
 
 
/**
* @}
*/
/branches/sparc/uspace/srv/kbd/arch/ia64/src/scanc.c
0,0 → 1,202
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdia32
* @brief Scancodes for PC keyboards.
* @{
*/
/** @file
* @ingroup kbdamd64
*/
 
#include <genarch/scanc.h>
 
/** Primary meaning of scancodes. */
int sc_primary_map[] = {
SPECIAL, /* 0x00 */
SPECIAL, /* 0x01 - Esc */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
'\b', /* 0x0e - Backspace */
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
SPECIAL, /* 0x1d - LCtrl */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'',
'`',
SPECIAL, /* 0x2a - LShift */
'\\',
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
(FUNCTION_KEYS | 1), /* 0x3b - F1 */
(FUNCTION_KEYS | 2), /* 0x3c - F2 */
(FUNCTION_KEYS | 3), /* 0x3d - F3 */
(FUNCTION_KEYS | 4), /* 0x3e - F4 */
(FUNCTION_KEYS | 5), /* 0x3f - F5 */
(FUNCTION_KEYS | 6), /* 0x40 - F6 */
(FUNCTION_KEYS | 7), /* 0x41 - F7 */
(FUNCTION_KEYS | 8), /* 0x42 - F8 */
(FUNCTION_KEYS | 9), /* 0x43 - F9 */
(FUNCTION_KEYS | 10), /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
(FUNCTION_KEYS | 11), /* 0x57 - F11 */
(FUNCTION_KEYS | 12), /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/** Secondary meaning of scancodes. */
int sc_secondary_map[] = {
SPECIAL, /* 0x00 */
0x1b, /* 0x01 - Esc */
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
SPECIAL, /* 0x0e - Backspace */
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
SPECIAL, /* 0x1d - LCtrl */
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"',
'~',
SPECIAL, /* 0x2a - LShift */
'|',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
SPECIAL, /* 0x3b - F1 */
SPECIAL, /* 0x3c - F2 */
SPECIAL, /* 0x3d - F3 */
SPECIAL, /* 0x3e - F4 */
SPECIAL, /* 0x3f - F5 */
SPECIAL, /* 0x40 - F6 */
SPECIAL, /* 0x41 - F7 */
SPECIAL, /* 0x42 - F8 */
SPECIAL, /* 0x43 - F9 */
SPECIAL, /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
SPECIAL, /* 0x57 - F11 */
SPECIAL, /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/**
* @}
*/
/branches/sparc/uspace/srv/kbd/arch/ia64/src/mouse.c
0,0 → 1,117
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <ipc/ipc.h>
#include <async.h>
#include <kbd.h>
#include <keys.h>
 
#define i8042_MOUSE_DATA 0x20
 
#define BUFSIZE 3
 
typedef struct {
union {
unsigned char data[BUFSIZE];
struct {
unsigned leftbtn : 1;
unsigned rightbtn : 1;
unsigned middlebtn : 1;
unsigned isone : 1; /* Always one */
unsigned xsign : 1;
unsigned ysign : 1;
unsigned xovfl : 1;
unsigned yovfl : 1;
unsigned char x;
unsigned char y;
} val;
}u;
}ps2packet_t;
 
static ps2packet_t buf;
static int bufpos = 0;
static int leftbtn = 0;
static int rightbtn = 0;
static int middlebtn = 0;
 
/** Convert 9-bit 2-complement signed number to integer */
static int bit9toint(int sign, unsigned char data)
{
int tmp;
 
if (!sign)
return data;
 
tmp = ((unsigned char)~data) + 1;
return -tmp;
}
 
/** Process mouse data
*
* @return True if mouse command was recognized and processed
*/
int mouse_arch_process(int phoneid, ipc_call_t *call)
{
int status = IPC_GET_ARG1(*call);
int data = IPC_GET_ARG2(*call);
int x,y;
 
if (!(status & i8042_MOUSE_DATA))
return 0;
 
/* Check that we have not lost synchronization */
if (bufpos == 0 && !(data & 0x8))
return 1; /* Synchro lost, ignore byte */
 
buf.u.data[bufpos++] = data;
if (bufpos == BUFSIZE) {
bufpos = 0;
if (phoneid != -1) {
if (buf.u.val.leftbtn ^ leftbtn) {
leftbtn = buf.u.val.leftbtn;
async_msg_1(phoneid, KBD_MS_LEFT, leftbtn);
}
if (buf.u.val.rightbtn & rightbtn) {
rightbtn = buf.u.val.middlebtn;
async_msg_1(phoneid, KBD_MS_RIGHT, rightbtn);
}
if (buf.u.val.rightbtn & rightbtn) {
middlebtn = buf.u.val.middlebtn;
async_msg_1(phoneid, KBD_MS_MIDDLE, middlebtn);
}
x = bit9toint(buf.u.val.xsign, buf.u.val.x);
y = bit9toint(buf.u.val.ysign, buf.u.val.y);
if (x || y)
async_msg_2(phoneid, KBD_MS_MOVE, (ipcarg_t)x,
(ipcarg_t)(-y));
}
}
 
return 1;
}
/branches/sparc/uspace/srv/kbd/arch/ia64/src/lkbd.c
0,0 → 1,166
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdia64 ia64
* @brief HelenOS ia64
* @ingroup kbd
* @{
*/
/** @file
* @ingroup kbdia64
*/
 
#include <arch/lkbd.h>
#include <ipc/ipc.h>
#include <unistd.h>
#include <kbd.h>
#include <keys.h>
#include <genarch/kbd.h>
#include <sysinfo.h>
 
/* Interesting bits for status register */
#define i8042_OUTPUT_FULL 0x1
#define i8042_INPUT_FULL 0x2
#define i8042_MOUSE_DATA 0x20
 
/* Command constants */
#define i8042_CMD_KBD 0x60
#define i8042_CMD_MOUSE 0xd4
 
/* Keyboard cmd byte */
#define i8042_KBD_IE 0x1
#define i8042_MOUSE_IE 0x2
#define i8042_KBD_DISABLE 0x10
#define i8042_MOUSE_DISABLE 0x20
#define i8042_KBD_TRANSLATE 0x40
 
/* Mouse constants */
#define MOUSE_OUT_INIT 0xf4
#define MOUSE_ACK 0xfa
 
#define KEY_RELEASE 0x80
 
static volatile int keyflags; /**< Tracking of multiple keypresses. */
static volatile int lockflags; /**< Tracking of multiple keys lockings. */
 
irq_cmd_t i8042_cmds[2] = {
{ CMD_PORT_READ_1, (void *) 0x64, 0, 1 },
{ CMD_PORT_READ_1, (void *) 0x60, 0, 2 }
};
 
irq_code_t i8042_kbd = {
2,
i8042_cmds
};
 
static void wait_ready(void) {
while (i8042_status_read() & i8042_INPUT_FULL)
;
}
 
/** Register uspace irq handler
* @return
*/
int lkbd_arch_init(void)
{
int i;
int mouseenabled = 0;
 
iospace_enable(task_get_id(), (void *) i8042_DATA, 5);
/* Disable kbd, enable mouse */
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_data_write(i8042_KBD_DISABLE);
wait_ready();
 
/* Flush all current IO */
while (i8042_status_read() & i8042_OUTPUT_FULL)
i8042_data_read();
/* 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 */
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &i8042_kbd);
 
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
if (mouseenabled)
newcontrol |= i8042_MOUSE_IE;
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_data_write(newcontrol);
wait_ready();
return 0;
}
 
/** Process keyboard & mouse events */
int lkbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
int status = IPC_GET_ARG1(*call);
 
if ((status & i8042_MOUSE_DATA))
return 0;
int scan_code = IPC_GET_ARG2(*call);
if (scan_code & KEY_RELEASE)
key_released(keybuffer, scan_code ^ KEY_RELEASE);
else
key_pressed(keybuffer, scan_code);
return 1;
}
 
/**
* @}
*/
/branches/sparc/uspace/srv/fb/ega.c
64,9 → 64,12
#define EGA_IO_ADDRESS 0x3d4
#define EGA_IO_SIZE 2
 
#define NORMAL_COLOR 0x0f
#define INVERTED_COLOR 0xf0
int ega_normal_color=0x0f;
int ega_inverted_color=0xf0;
 
#define NORMAL_COLOR ega_normal_color
#define INVERTED_COLOR ega_inverted_color
 
#define EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR)
 
/* Allow only 1 connection */
76,7 → 79,7
static unsigned int scr_height;
static char *scr_addr;
 
static unsigned int style = NORMAL_COLOR;
static unsigned int style;
 
static void clrscr(void)
{
312,6 → 315,13
ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
scr_width = sysinfo_value("fb.width");
scr_height = sysinfo_value("fb.height");
if(sysinfo_value("fb.blinking"))
{
ega_normal_color&=0x77;
ega_inverted_color&=0x77;
}
style = NORMAL_COLOR;
 
iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2);
 
sz = scr_width * scr_height * 2;
/branches/sparc/uspace/srv/fb/Makefile
56,6 → 56,10
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), ia64)
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), amd64)
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
/branches/sparc/uspace/srv/fs/tmpfs/tmpfs_dump.c
59,6 → 59,7
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
do {
char *fname;
93,7 → 94,8
}
fname[entry.len] = 0;
if (!ops->link((void *) parent, (void *) node, fname)) {
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
134,8 → 136,9
return false;
}
fname[entry.len] = 0;
if (!ops->link((void *) parent, (void *) node, fname)) {
 
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
/branches/sparc/uspace/srv/fs/tmpfs/tmpfs_ops.c
75,7 → 75,7
static void *tmpfs_node_get(dev_handle_t, fs_index_t);
static void tmpfs_node_put(void *);
static void *tmpfs_create_node(dev_handle_t, int);
static bool tmpfs_link_node(void *, void *, const char *);
static int tmpfs_link_node(void *, void *, const char *);
static int tmpfs_unlink_node(void *, void *);
static int tmpfs_destroy_node(void *);
 
308,7 → 308,7
return (void *) node;
}
 
bool tmpfs_link_node(void *prnt, void *chld, const char *nm)
int tmpfs_link_node(void *prnt, void *chld, const char *nm)
{
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt;
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld;
317,13 → 317,13
 
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t));
if (!namep)
return false;
return ENOMEM;
tmpfs_name_initialize(namep);
size_t len = strlen(nm);
namep->name = malloc(len + 1);
if (!namep->name) {
free(namep);
return false;
return ENOMEM;
}
strcpy(namep->name, nm);
namep->parent = parentp;
343,7 → 343,7
parentp->child = childp;
}
 
return true;
return EOK;
}
 
int tmpfs_unlink_node(void *prnt, void *chld)
/branches/sparc/uspace/srv/fs/fat/fat_idx.c
214,7 → 214,7
};
 
/** Allocate a VFS index which is not currently in use. */
static bool fat_idx_alloc(dev_handle_t dev_handle, fs_index_t *index)
static bool fat_index_alloc(dev_handle_t dev_handle, fs_index_t *index)
{
unused_t *u;
276,7 → 276,7
}
 
/** Free a VFS index, which is no longer in use. */
static void fat_idx_free(dev_handle_t dev_handle, fs_index_t index)
static void fat_index_free(dev_handle_t dev_handle, fs_index_t index)
{
unused_t *u;
 
338,7 → 338,7
futex_up(&unused_futex);
}
 
static fat_idx_t *fat_idx_get_new_core(dev_handle_t dev_handle)
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
{
fat_idx_t *fidx;
 
345,7 → 345,7
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
if (!fidx)
return NULL;
if (!fat_idx_alloc(dev_handle, &fidx->index)) {
if (!fat_index_alloc(dev_handle, &fidx->index)) {
free(fidx);
return NULL;
}
366,7 → 366,7
fat_idx_t *fidx;
 
futex_down(&used_futex);
fidx = fat_idx_get_new_core(dev_handle);
fidx = fat_idx_create(dev_handle);
if (!fidx) {
futex_up(&used_futex);
return NULL;
400,7 → 400,7
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
} else {
fidx = fat_idx_get_new_core(dev_handle);
fidx = fat_idx_create(dev_handle);
if (!fidx) {
futex_up(&used_futex);
return NULL;
423,6 → 423,32
return fidx;
}
 
void fat_idx_hashin(fat_idx_t *idx)
{
unsigned long pkey[] = {
[UPH_DH_KEY] = idx->dev_handle,
[UPH_PFC_KEY] = idx->pfc,
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
hash_table_insert(&up_hash, pkey, &idx->uph_link);
futex_up(&used_futex);
}
 
void fat_idx_hashout(fat_idx_t *idx)
{
unsigned long pkey[] = {
[UPH_DH_KEY] = idx->dev_handle,
[UPH_PFC_KEY] = idx->pfc,
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
hash_table_remove(&up_hash, pkey, 3);
futex_up(&used_futex);
}
 
fat_idx_t *
fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index)
{
444,6 → 470,33
return fidx;
}
 
/** Destroy the index structure.
*
* @param idx The index structure to be destroyed.
*/
void fat_idx_destroy(fat_idx_t *idx)
{
unsigned long ikey[] = {
[UIH_DH_KEY] = idx->dev_handle,
[UIH_INDEX_KEY] = idx->index,
};
 
assert(idx->pfc == FAT_CLST_RES0);
 
futex_down(&used_futex);
/*
* Since we can only free unlinked nodes, the index structure is not
* present in the position hash (uph). We therefore hash it out from
* the index hash only.
*/
hash_table_remove(&ui_hash, ikey, 2);
futex_up(&used_futex);
/* Release the VFS index. */
fat_index_free(idx->dev_handle, idx->index);
/* Deallocate the structure. */
free(idx);
}
 
int fat_idx_init(void)
{
if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops))
/branches/sparc/uspace/srv/fs/fat/fat.h
203,9 → 203,14
extern void fat_read(ipc_callid_t, ipc_call_t *);
extern void fat_write(ipc_callid_t, ipc_call_t *);
extern void fat_truncate(ipc_callid_t, ipc_call_t *);
extern void fat_destroy(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_new(dev_handle_t);
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
extern void fat_idx_destroy(fat_idx_t *);
extern void fat_idx_hashin(fat_idx_t *);
extern void fat_idx_hashout(fat_idx_t *);
 
extern int fat_idx_init(void);
extern void fat_idx_fini(void);
/branches/sparc/uspace/srv/fs/fat/fat_dentry.c
36,16 → 36,81
*/
 
#include "fat_dentry.h"
#include <ctype.h>
#include <string.h>
 
#define FAT_PAD ' '
static bool is_d_char(const char ch)
{
if (isalnum(ch) || ch == '_')
return true;
else
return false;
}
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
/** Compare path component with the name read from the dentry.
*
* This function compares the path component with the name read from the dentry.
* The comparison is case insensitive and tolerates a mismatch on the trailing
* dot character at the end of the name (i.e. when there is a dot, but no
* extension).
*
* @param name Node name read from the dentry.
* @param component Path component.
*
* @return Zero on match, non-zero otherwise.
*/
int fat_dentry_namecmp(char *name, const char *component)
{
int rc;
if (!(rc = stricmp(name, component)))
return rc;
if (!strchr(name, '.')) {
/*
* There is no '.' in the name, so we know that there is enough
* space for appending an extra '.' to name.
*/
name[strlen(name)] = '.';
name[strlen(name) + 1] = '\0';
rc = stricmp(name, component);
}
return rc;
}
 
void dentry_name_canonify(fat_dentry_t *d, char *buf)
bool fat_dentry_name_verify(const char *name)
{
unsigned i, dot;
bool dot_found = false;
 
for (i = 0; name[i]; i++) {
if (name[i] == '.') {
if (dot_found) {
return false;
} else {
dot_found = true;
dot = i;
}
} else {
if (!is_d_char(name[i]))
return false;
}
}
 
if (dot_found) {
if (dot > FAT_NAME_LEN)
return false;
if (i - dot > FAT_EXT_LEN + 1)
return false;
} else {
if (i > FAT_NAME_LEN)
return false;
}
 
return true;
}
 
void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
{
int i;
 
for (i = 0; i < FAT_NAME_LEN; i++) {
71,8 → 136,47
*buf = '\0';
}
 
fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
void fat_dentry_name_set(fat_dentry_t *d, const char *name)
{
int i;
const char fake_ext[] = " ";
 
 
for (i = 0; i < FAT_NAME_LEN; i++) {
switch ((uint8_t) *name) {
case 0xe5:
d->name[i] = FAT_DENTRY_E5_ESC;
name++;
break;
case '\0':
case '.':
d->name[i] = FAT_PAD;
break;
default:
d->name[i] = toupper(*name++);
break;
}
}
if (*name++ != '.')
name = fake_ext;
for (i = 0; i < FAT_EXT_LEN; i++) {
switch ((uint8_t) *name) {
case 0xe5:
d->ext[i] = FAT_DENTRY_E5_ESC;
name++;
break;
case '\0':
d->ext[i] = FAT_PAD;
break;
default:
d->ext[i] = toupper(*name++);
break;
}
}
}
 
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
{
if (d->attr & FAT_ATTR_VOLLABEL) {
/* volume label entry */
return FAT_DENTRY_SKIP;
79,7 → 183,7
}
if (d->name[0] == FAT_DENTRY_ERASED) {
/* not-currently-used entry */
return FAT_DENTRY_SKIP;
return FAT_DENTRY_FREE;
}
if (d->name[0] == FAT_DENTRY_UNUSED) {
/* never used entry */
/branches/sparc/uspace/srv/fs/fat/fat_dentry.h
34,17 → 34,30
#define FAT_FAT_DENTRY_H_
 
#include <stdint.h>
#include <bool.h>
 
#define FAT_NAME_LEN 8
#define FAT_EXT_LEN 3
 
#define FAT_NAME_DOT ". "
#define FAT_NAME_DOT_DOT ".. "
#define FAT_EXT_PAD " "
 
#define FAT_ATTR_RDONLY (1 << 0)
#define FAT_ATTR_VOLLABEL (1 << 3)
#define FAT_ATTR_SUBDIR (1 << 4)
 
#define FAT_PAD ' '
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
 
typedef enum {
FAT_DENTRY_SKIP,
FAT_DENTRY_LAST,
FAT_DENTRY_FREE,
FAT_DENTRY_VALID
} fat_dentry_clsf_t;
 
70,8 → 83,11
uint32_t size;
} __attribute__ ((packed)) fat_dentry_t;
 
extern void dentry_name_canonify(fat_dentry_t *, char *);
extern fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *);
extern int fat_dentry_namecmp(char *, const char *);
extern bool fat_dentry_name_verify(const char *);
extern void fat_dentry_name_get(const fat_dentry_t *, char *);
extern void fat_dentry_name_set(fat_dentry_t *, const char *);
extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
 
#endif
 
/branches/sparc/uspace/srv/fs/fat/fat_fat.c
182,7 → 182,7
boundary = ROUND_UP(nodep->size, bps * spc);
 
/* zero out already allocated space */
for (o = nodep->size - 1; o < pos && o < boundary;
for (o = nodep->size; o < pos && o < boundary;
o = ALIGN_DOWN(o + bps, bps)) {
int flags = (o % bps == 0) ?
BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
285,10 → 285,10
}
}
 
/** Allocate clusters in FAT1.
/** Allocate clusters in all copies of FAT.
*
* This function will attempt to allocate the requested number of clusters in
* the first FAT instance. The FAT will be altered so that the allocated
* all instances of the FAT. The FAT will be altered so that the allocated
* clusters form an independent chain (i.e. a chain which does not belong to any
* file yet).
*
315,7 → 315,7
unsigned b, c, cl;
 
lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
if (lifo)
if (!lifo)
return ENOMEM;
bps = uint16_t_le2host(bs->bps);
326,8 → 326,8
* Search FAT1 for unused clusters.
*/
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; blk++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NOREAD);
for (b = 0, cl = 0; b < sf; b++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
385,8 → 385,8
 
/* Mark all clusters in the chain as free in all copies of FAT. */
while (firstc < FAT_CLST_LAST1) {
assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
nextc = fat_get_cluster(bs, dev_handle, firstc);
assert(nextc >= FAT_CLST_FIRST && nextc < FAT_CLST_BAD);
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_set_cluster(bs, dev_handle, fatno, firstc,
FAT_CLST_RES0);
409,7 → 409,7
if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
(uint16_t) -1) == 0) {
/* No clusters allocated to the node yet. */
nodep->firstc = host2uint16_t_le(mcl);
nodep->firstc = mcl;
nodep->dirty = true; /* need to sync node */
return;
}
/branches/sparc/uspace/srv/fs/fat/fat.c
116,6 → 116,9
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_DESTROY:
fat_destroy(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/sparc/uspace/srv/fs/fat/fat_ops.c
94,10 → 94,14
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
 
d->firstc = host2uint16_t_le(node->firstc);
if (node->type == FAT_FILE)
if (node->type == FAT_FILE) {
d->size = host2uint32_t_le(node->size);
/* TODO: update other fields? (e.g time fields, attr field) */
} else if (node->type == FAT_DIRECTORY) {
d->attr = FAT_ATTR_SUBDIR;
}
/* TODO: update other fields? (e.g time fields) */
b->dirty = true; /* need to sync block */
block_put(b);
}
216,8 → 220,31
return nodep;
}
 
/*
* Forward declarations of FAT libfs operations.
*/
static void *fat_node_get(dev_handle_t, fs_index_t);
static void fat_node_put(void *);
static void *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(void *);
static int fat_link(void *, void *, const char *);
static int fat_unlink(void *, void *);
static void *fat_match(void *, const char *);
static fs_index_t fat_index_get(void *);
static size_t fat_size_get(void *);
static unsigned fat_lnkcnt_get(void *);
static bool fat_has_children(void *);
static void *fat_root_get(dev_handle_t);
static char fat_plb_get_char(unsigned);
static bool fat_is_directory(void *);
static bool fat_is_file(void *node);
 
/*
* FAT libfs operations.
*/
 
/** Instantiate a FAT in-core node. */
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
{
void *node;
fat_idx_t *idxp;
231,40 → 258,297
return node;
}
 
static void fat_node_put(void *node)
void fat_node_put(void *node)
{
fat_node_t *nodep = (fat_node_t *)node;
bool destroy = false;
 
futex_down(&nodep->lock);
if (!--nodep->refcnt) {
futex_down(&ffn_futex);
list_append(&nodep->ffn_link, &ffn_head);
futex_up(&ffn_futex);
if (nodep->idx) {
futex_down(&ffn_futex);
list_append(&nodep->ffn_link, &ffn_head);
futex_up(&ffn_futex);
} else {
/*
* The node does not have any index structure associated
* with itself. This can only mean that we are releasing
* the node after a failed attempt to allocate the index
* structure for it.
*/
destroy = true;
}
}
futex_up(&nodep->lock);
if (destroy)
free(node);
}
 
static void *fat_create(dev_handle_t dev_handle, int flags)
void *fat_create_node(dev_handle_t dev_handle, int flags)
{
return NULL; /* not supported at the moment */
fat_idx_t *idxp;
fat_node_t *nodep;
fat_bs_t *bs;
fat_cluster_t mcl, lcl;
uint16_t bps;
int rc;
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
if (flags & L_DIRECTORY) {
/* allocate a cluster */
rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
if (rc != EOK)
return NULL;
}
 
nodep = fat_node_get_new();
if (!nodep) {
fat_free_clusters(bs, dev_handle, mcl);
return NULL;
}
idxp = fat_idx_get_new(dev_handle);
if (!idxp) {
fat_free_clusters(bs, dev_handle, mcl);
fat_node_put(nodep);
return NULL;
}
/* idxp->lock held */
if (flags & L_DIRECTORY) {
int i;
block_t *b;
 
/*
* Populate the new cluster with unused dentries.
*/
for (i = 0; i < bs->spc; i++) {
b = _fat_block_get(bs, dev_handle, mcl, i,
BLOCK_FLAGS_NOREAD);
/* mark all dentries as never-used */
memset(b->data, 0, bps);
b->dirty = false;
block_put(b);
}
nodep->type = FAT_DIRECTORY;
nodep->firstc = mcl;
nodep->size = bps * bs->spc;
} else {
nodep->type = FAT_FILE;
nodep->firstc = FAT_CLST_RES0;
nodep->size = 0;
}
nodep->lnkcnt = 0; /* not linked anywhere */
nodep->refcnt = 1;
nodep->dirty = true;
 
nodep->idx = idxp;
idxp->nodep = nodep;
 
futex_up(&idxp->lock);
return nodep;
}
 
static int fat_destroy(void *node)
int fat_destroy_node(void *node)
{
return ENOTSUP; /* not supported at the moment */
fat_node_t *nodep = (fat_node_t *)node;
fat_bs_t *bs;
 
/*
* The node is not reachable from the file system. This means that the
* link count should be zero and that the index structure cannot be
* found in the position hash. Obviously, we don't need to lock the node
* nor its index structure.
*/
assert(nodep->lnkcnt == 0);
 
/*
* The node may not have any children.
*/
assert(fat_has_children(node) == false);
 
bs = block_bb_get(nodep->idx->dev_handle);
if (nodep->firstc != FAT_CLST_RES0) {
assert(nodep->size);
/* Free all clusters allocated to the node. */
fat_free_clusters(bs, nodep->idx->dev_handle, nodep->firstc);
}
 
fat_idx_destroy(nodep->idx);
free(nodep);
return EOK;
}
 
static bool fat_link(void *prnt, void *chld, const char *name)
int fat_link(void *prnt, void *chld, const char *name)
{
return false; /* not supported at the moment */
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_dentry_t *d;
fat_bs_t *bs;
block_t *b;
int i, j;
uint16_t bps;
unsigned dps;
unsigned blocks;
 
futex_down(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
futex_up(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
futex_up(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
* Attempt to create unsupported name.
*/
return ENOTSUP;
}
 
/*
* Get us an unused parent node's dentry or grow the parent and allocate
* a new one.
*/
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
blocks = parentp->size / bps;
 
for (i = 0; i < blocks; i++) {
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_VALID:
/* skipping used and meta entries */
continue;
case FAT_DENTRY_FREE:
case FAT_DENTRY_LAST:
/* found an empty slot */
goto hit;
}
}
block_put(b);
}
/*
* We need to grow the parent in order to create a new unused dentry.
*/
futex_up(&parentp->idx->lock);
return ENOTSUP; /* XXX */
 
hit:
/*
* At this point we only establish the link between the parent and the
* child. The dentry, except of the name and the extension, will remain
* uninitialized until the the corresponding node is synced. Thus the
* valid dentry data is kept in the child node structure.
*/
memset(d, 0, sizeof(fat_dentry_t));
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
futex_up(&parentp->idx->lock);
 
futex_down(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
* Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
* are not mandatory according to Standard ECMA-107 and HelenOS VFS does
* not use them anyway, so this is rather a sign of our good will.
*/
b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE);
d = (fat_dentry_t *)b->data;
if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
strcmp(d->name, FAT_NAME_DOT) == 0) {
memset(d, 0, sizeof(fat_dentry_t));
strcpy(d->name, FAT_NAME_DOT);
strcpy(d->ext, FAT_EXT_PAD);
d->attr = FAT_ATTR_SUBDIR;
d->firstc = host2uint16_t_le(childp->firstc);
/* TODO: initialize also the date/time members. */
}
d++;
if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
strcmp(d->name, FAT_NAME_DOT_DOT) == 0) {
memset(d, 0, sizeof(fat_dentry_t));
strcpy(d->name, FAT_NAME_DOT_DOT);
strcpy(d->ext, FAT_EXT_PAD);
d->attr = FAT_ATTR_SUBDIR;
d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
host2uint16_t_le(FAT_CLST_RES0) :
host2uint16_t_le(parentp->firstc);
/* TODO: initialize also the date/time members. */
}
b->dirty = true; /* need to sync block */
block_put(b);
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
futex_up(&childp->idx->lock);
 
futex_down(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
futex_up(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
*/
fat_idx_hashin(childp->idx);
 
return EOK;
}
 
static int fat_unlink(void *prnt, void *chld)
int fat_unlink(void *prnt, void *chld)
{
return ENOTSUP; /* not supported at the moment */
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
block_t *b;
 
futex_down(&parentp->lock);
futex_down(&childp->lock);
assert(childp->lnkcnt == 1);
futex_down(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
b = _fat_block_get(bs, childp->idx->dev_handle, childp->idx->pfc,
(childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
BLOCK_FLAGS_NONE);
d = (fat_dentry_t *)b->data +
(childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
/* mark the dentry as not-currently-used */
d->name[0] = FAT_DENTRY_ERASED;
b->dirty = true; /* need to sync block */
block_put(b);
 
/* remove the index structure from the position hash */
fat_idx_hashout(childp->idx);
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
futex_up(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
futex_up(&childp->lock);
futex_up(&parentp->lock);
 
return EOK;
}
 
static void *fat_match(void *prnt, const char *component)
void *fat_match(void *prnt, const char *component)
{
fat_bs_t *bs;
fat_node_t *parentp = (fat_node_t *)prnt;
287,6 → 571,7
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
294,10 → 579,10
return NULL;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
break;
}
if (stricmp(name, component) == 0) {
if (fat_dentry_namecmp(name, component) == 0) {
/* hit */
void *node;
/*
331,7 → 616,7
return NULL;
}
 
static fs_index_t fat_index_get(void *node)
fs_index_t fat_index_get(void *node)
{
fat_node_t *fnodep = (fat_node_t *)node;
if (!fnodep)
339,17 → 624,17
return fnodep->idx->index;
}
 
static size_t fat_size_get(void *node)
size_t fat_size_get(void *node)
{
return ((fat_node_t *)node)->size;
}
 
static unsigned fat_lnkcnt_get(void *node)
unsigned fat_lnkcnt_get(void *node)
{
return ((fat_node_t *)node)->lnkcnt;
}
 
static bool fat_has_children(void *node)
bool fat_has_children(void *node)
{
fat_bs_t *bs;
fat_node_t *nodep = (fat_node_t *)node;
377,6 → 662,7
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
399,22 → 685,22
return false;
}
 
static void *fat_root_get(dev_handle_t dev_handle)
void *fat_root_get(dev_handle_t dev_handle)
{
return fat_node_get(dev_handle, 0);
}
 
static char fat_plb_get_char(unsigned pos)
char fat_plb_get_char(unsigned pos)
{
return fat_reg.plb_ro[pos % PLB_SIZE];
}
 
static bool fat_is_directory(void *node)
bool fat_is_directory(void *node)
{
return ((fat_node_t *)node)->type == FAT_DIRECTORY;
}
 
static bool fat_is_file(void *node)
bool fat_is_file(void *node)
{
return ((fat_node_t *)node)->type == FAT_FILE;
}
424,8 → 710,8
.match = fat_match,
.node_get = fat_node_get,
.node_put = fat_node_put,
.create = fat_create,
.destroy = fat_destroy,
.create = fat_create_node,
.destroy = fat_destroy_node,
.link = fat_link,
.unlink = fat_unlink,
.index_get = fat_index_get,
438,6 → 724,10
.is_file = fat_is_file
};
 
/*
* VFS operations.
*/
 
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
607,6 → 897,7
d = ((fat_dentry_t *)b->data) + o;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
613,7 → 904,7
goto miss;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
block_put(b);
goto hit;
}
799,6 → 1090,22
return;
}
 
void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
int rc;
 
fat_node_t *nodep = fat_node_get(dev_handle, index);
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
 
rc = fat_destroy_node(nodep);
ipc_answer_0(rid, rc);
}
 
/**
* @}
*/
/branches/sparc/uspace/srv/vfs/vfs_ops.c
234,6 → 234,7
mr_res.triplet.index = (fs_index_t) rindex;
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;
302,6 → 303,16
int mode = IPC_GET_ARG3(*request);
size_t len;
 
/*
* Make sure that we are called with exactly one of L_FILE and
* L_DIRECTORY.
*/
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
ipc_answer_0(rid, EINVAL);
return;
}
 
if (oflag & O_CREAT)
lflag |= L_CREATE;
if (oflag & O_EXCL)
456,7 → 467,7
* the same open file at a time.
*/
futex_down(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
* the same time.
465,6 → 476,15
rwlock_read_lock(&file->node->contents_rwlock);
else
rwlock_write_lock(&file->node->contents_rwlock);
 
if (file->node->type == VFS_NODE_DIRECTORY) {
/*
* Make sure that no one is modifying the namespace
* while we are in readdir().
*/
assert(read);
rwlock_read_lock(&namespace_rwlock);
}
int fs_phone = vfs_grab_phone(file->node->fs_handle);
490,6 → 510,9
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
rwlock_read_unlock(&namespace_rwlock);
/* Unlock the VFS node. */
if (read)
/branches/sparc/uspace/srv/vfs/vfs.h
190,8 → 190,15
*/
#define L_PARENT 64
 
typedef enum vfs_node_type {
VFS_NODE_UNKNOWN,
VFS_NODE_FILE,
VFS_NODE_DIRECTORY,
} vfs_node_type_t;
 
typedef struct {
vfs_triplet_t triplet;
vfs_node_type_t type;
size_t size;
unsigned lnkcnt;
} vfs_lookup_res_t;
213,6 → 220,9
unsigned lnkcnt;
 
link_t nh_link; /**< Node hash-table link. */
 
vfs_node_type_t type; /**< Partial info about the node type. */
 
size_t size; /**< Cached size if the node is a file. */
 
/**
/branches/sparc/uspace/srv/vfs/vfs_node.c
175,15 → 175,22
node->index = result->triplet.index;
node->size = result->size;
node->lnkcnt = result->lnkcnt;
node->type = result->type;
link_initialize(&node->nh_link);
rwlock_initialize(&node->contents_rwlock);
hash_table_insert(&nodes, key, &node->nh_link);
} else {
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
if (node->type == VFS_NODE_UNKNOWN &&
result->type != VFS_NODE_UNKNOWN) {
/* Upgrade the node type. */
node->type = result->type;
}
}
 
assert(node->size == result->size);
assert(node->lnkcnt == result->lnkcnt);
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN);
 
_vfs_node_addref(node);
futex_up(&nodes_futex);
/branches/sparc/uspace/srv/vfs/vfs_lookup.c
182,6 → 182,12
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
result->size = (size_t) IPC_GET_ARG4(answer);
result->lnkcnt = (unsigned) IPC_GET_ARG5(answer);
if (lflag & L_FILE)
result->type = VFS_NODE_FILE;
else if (lflag & L_DIRECTORY)
result->type = VFS_NODE_DIRECTORY;
else
result->type = VFS_NODE_UNKNOWN;
}
 
return rc;