/branches/dynload/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); |
if (argc < 2) { |
printf("\n"); |
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; |
} |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
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; |
} |
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose); |
if (verbose) |
printf("%d bytes copied\n", ret); |
if (ret >= 0) |
return CMD_SUCCESS; |
else |
return CMD_FAILURE; |
} |
/branches/dynload/uspace/app/init/init.c |
---|
116,6 → 116,7 |
console_wait(); |
version_print(); |
spawn("/app/klog"); |
spawn("/app/bdsh"); |
free(buf); |
/branches/dynload/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/dynload/uspace/app/tester/loop/loop1.def |
---|
0,0 → 1,6 |
{ |
"loop1", |
"Endless loop", |
&test_loop1, |
false |
}, |
/branches/dynload/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/dynload/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/dynload/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/dynload/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/dynload/uspace/dist/readme |
---|
0,0 → 1,0 |
Lorem ipsum. |
/branches/dynload/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/dynload/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/dynload/uspace/lib/libc/include/libc.h |
---|
39,12 → 39,18 |
#include <kernel/syscall/syscall.h> |
#include <libarch/syscall.h> |
#define __SYSCALL0(id) __syscall0(0, 0, 0, 0, 0, 0, id) |
#define __SYSCALL1(id, p1) __syscall1(p1, 0, 0, 0, 0, 0, id) |
#define __SYSCALL2(id, p1, p2) __syscall2(p1, p2, 0, 0, 0, 0, id) |
#define __SYSCALL3(id, p1, p2, p3) __syscall3(p1, p2, p3, 0, 0, 0, id) |
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall4(p1, p2, p3, p4, 0, 0, id) |
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall5(p1, p2, p3, p4, p5, 0, id) |
#define __SYSCALL0(id) \ |
__syscall0(0, 0, 0, 0, 0, 0, id) |
#define __SYSCALL1(id, p1) \ |
__syscall1(p1, 0, 0, 0, 0, 0, id) |
#define __SYSCALL2(id, p1, p2) \ |
__syscall2(p1, p2, 0, 0, 0, 0, id) |
#define __SYSCALL3(id, p1, p2, p3) \ |
__syscall3(p1, p2, p3, 0, 0, 0, id) |
#define __SYSCALL4(id, p1, p2, p3, p4) \ |
__syscall4(p1, p2, p3, p4, 0, 0, id) |
#define __SYSCALL5(id, p1, p2, p3, p4, p5) \ |
__syscall5(p1, p2, p3, p4, p5, 0, id) |
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \ |
__syscall6(p1, p2, p3, p4, p5, p6, id) |
/branches/dynload/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/dynload/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/dynload/uspace/lib/libc/include/errno.h |
---|
47,6 → 47,7 |
#define ERANGE (-263) |
#define EXDEV (-264) |
#define EIO (-265) |
#define EMLINK (-266) |
#endif |
/branches/dynload/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/dynload/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/dynload/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/dynload/uspace/srv/kbd/genarch/include/nofb.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_genarch_NOFB_H_ |
#define KBD_genarch_NOFB_H_ |
#include <key_buffer.h> |
#include <genarch/scanc.h> |
extern int kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code); |
#endif |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/kbd/genarch/src/nofb.c |
---|
0,0 → 1,187 |
/* |
* 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 kbdmips32 mips32 |
* @brief HelenOS mips32 arch dependent parts of uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#include <genarch/nofb.h> |
#include <stdio.h> // DELETE!!! |
#define KEY_F1 0x504f1bL |
#define KEY_F2 0x514f1bL |
#define KEY_F3 0x524f1bL |
#define KEY_F4 0x534f1bL |
#define KEY_F5 0x35315b1bL |
#define KEY_F6 0x37315b1bL |
#define KEY_F7 0x38315b1bL |
#define KEY_F8 0x39315b1bL |
#define KEY_F9 0x30325b1bL |
#define KEY_F10 0x31325b1bL |
#define KEY_F11 0x33325b1bL |
#define KEY_F12 0x34325b1bL |
/** |
* Processes the key pressed - pushes the key code into the key buffer. |
* Used in MSIM and Serengeti, i.e. non-framebuffer consoles. |
*/ |
int kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code) |
{ |
static unsigned long buf = 0; |
static int count = 0; |
if(scan_code == 0x7e) { |
switch (buf) { |
case KEY_F5: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 5); |
buf = count = 0; |
return 1; |
case KEY_F6: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 6); |
buf = count = 0; |
return 1; |
case KEY_F7: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 7); |
buf = count = 0; |
return 1; |
case KEY_F8: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 8); |
buf = count = 0; |
return 1; |
case KEY_F9: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 9); |
buf = count = 0; |
return 1; |
case KEY_F10: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 10); |
buf = count = 0; |
return 1; |
case KEY_F11: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 11); |
buf = count = 0; |
return 1; |
case KEY_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) != (KEY_F1 & 0xff)) { |
keybuffer_push(keybuffer, buf); |
buf = count = 0; |
return 1; |
} |
if (count <= 1) |
return 1; |
if ((buf & 0xffff) != (KEY_F1 & 0xffff) |
&& (buf & 0xffff) != (KEY_F5 & 0xffff) ) { |
keybuffer_push(keybuffer, buf & 0xff); |
keybuffer_push(keybuffer, (buf >> 8) &0xff); |
buf = count = 0; |
return 1; |
} |
if (count <= 2) |
return 1; |
switch (buf) { |
case KEY_F1: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 1); |
buf = count = 0; |
return 1; |
case KEY_F2: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 2); |
buf = count = 0; |
return 1; |
case KEY_F3: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 3); |
buf = count = 0; |
return 1; |
case KEY_F4: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 4); |
buf = count = 0; |
return 1; |
} |
if((buf & 0xffffff) != (KEY_F5 & 0xffffff) |
&& (buf & 0xffffff) != (KEY_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 KEY_F5: |
case KEY_F6: |
case KEY_F7: |
case KEY_F8: |
case KEY_F9: |
case KEY_F10: |
case KEY_F11: |
case KEY_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; |
} |
/** @} |
*/ |
/branches/dynload/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 \ |
69,16 → 78,21 |
endif |
ifeq ($(ARCH), sparc64) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/scanc.c |
arch/$(ARCH)/src/scanc.c \ |
arch/$(ARCH)/src/sgcn.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
genarch/src/kbd.c \ |
genarch/src/nofb.c |
endif |
ifeq ($(ARCH), arm32) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/kbd_gxemul.c |
endif |
ifeq ($(ARCH), mips32) |
GENARCH_SOURCES += \ |
genarch/src/nofb.c |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES))) |
/branches/dynload/uspace/srv/kbd/arch/sparc64/include/sgcn.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* 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 kbdsparc64 sparc64 |
* @brief Serengeti-specific parts of uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_sparc64_SGCN_H_ |
#define KBD_sparc64_SGCN_H_ |
void sgcn_init(void); |
void sgcn_key_pressed(void); |
#endif |
/** @} |
*/ |
/branches/dynload/uspace/srv/kbd/arch/sparc64/src/kbd.c |
---|
35,6 → 35,7 |
*/ |
#include <arch/kbd.h> |
#include <arch/sgcn.h> |
#include <ipc/ipc.h> |
#include <sysinfo.h> |
#include <kbd.h> |
78,6 → 79,7 |
#define KBD_Z8530 1 |
#define KBD_NS16550 2 |
#define KBD_SGCN 3 |
int kbd_arch_init(void) |
{ |
91,6 → 93,9 |
ns16550_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual"); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ns16550_kbd); |
break; |
case KBD_SGCN: |
sgcn_init(); |
break; |
default: |
break; |
} |
100,6 → 105,11 |
/** Process keyboard events */ |
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call) |
{ |
if (sysinfo_value("kbd.type") == KBD_SGCN) { |
sgcn_key_pressed(); |
return 1; |
} |
int scan_code = IPC_GET_ARG1(*call); |
if (scan_code == KBD_ALL_KEYS_UP) |
/branches/dynload/uspace/srv/kbd/arch/sparc64/src/sgcn.c |
---|
0,0 → 1,147 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* 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 kbdsparc64 sparc64 |
* @brief Serengeti-specific parts of uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/sgcn.h> |
#include <as.h> |
#include <ddi.h> |
#include <ipc/ipc.h> |
#include <kbd.h> |
#include <genarch/nofb.h> |
#include <genarch/kbd.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <futex.h> |
/** |
* SGCN buffer header. It is placed at the very beginning of the SGCN |
* buffer. |
*/ |
typedef struct { |
/** hard-wired to "CON" */ |
char magic[4]; |
/** we don't need this */ |
char unused[8]; |
/** offset within the SGCN buffer of the input buffer start */ |
uint32_t in_begin; |
/** offset within the SGCN buffer of the input buffer end */ |
uint32_t in_end; |
/** offset within the SGCN buffer of the input buffer read pointer */ |
uint32_t in_rdptr; |
/** offset within the SGCN buffer of the input buffer write pointer */ |
uint32_t in_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the console buffer beginning. |
*/ |
#define SGCN_BUFFER(type, offset) \ |
((type *) (sram_virt_addr + sram_buffer_offset + (offset))) |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
extern keybuffer_t keybuffer; |
/** |
* Virtual address mapped to SRAM. |
*/ |
static uintptr_t sram_virt_addr; |
/** |
* SGCN buffer offset within SGCN. |
*/ |
static uintptr_t sram_buffer_offset; |
/** |
* Initializes the SGCN driver. |
* Maps the physical memory (SRAM) and registers the interrupt. |
*/ |
void sgcn_init(void) |
{ |
sram_virt_addr = (uintptr_t) as_get_mappable_page( |
sysinfo_value("sram.area.size")); |
int result = physmem_map( |
(void *) sysinfo_value("sram.address.physical"), |
(void *) sram_virt_addr, |
sysinfo_value("sram.area.size") / PAGE_SIZE, |
AS_AREA_READ | AS_AREA_WRITE |
); |
if (result != 0) { |
printf("SGCN: uspace driver could not map physical memory."); |
} |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, (void *) 0); |
} |
/** |
* Handler of the "key pressed" event. Reads codes of all the pressed keys from |
* the buffer. |
*/ |
void sgcn_key_pressed(void) |
{ |
char c; |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
uint32_t size = end - begin; |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
if (c == '\r') { |
c = '\n'; |
} |
kbd_process_no_fb(&keybuffer, c); |
} |
} |
/** @} |
*/ |
/branches/dynload/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/dynload/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/dynload/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,9 → 164,158 |
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; |
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/dynload/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/dynload/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/dynload/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/dynload/uspace/srv/kbd/arch/mips32/src/kbd.c |
---|
34,6 → 34,7 |
/** @file |
*/ |
#include <arch/kbd.h> |
#include <genarch/nofb.h> |
#include <ipc/ipc.h> |
#include <sysinfo.h> |
#include <kbd.h> |
99,146 → 100,6 |
} |
*/ |
static int kbd_arch_process_no_fb(keybuffer_t *keybuffer, int scan_code) |
{ |
static unsigned long buf = 0; |
static int count = 0; |
/* Please preserve this code (it can be used to determine scancodes) |
keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf)); |
keybuffer_push(keybuffer, to_hex(scan_code&0xf)); |
keybuffer_push(keybuffer, ' '); |
keybuffer_push(keybuffer, ' '); |
return 1; |
*/ |
if(scan_code == 0x7e) { |
switch (buf) { |
case MSIM_KEY_F5: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 5); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F6: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 6); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F7: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 7); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F8: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 8); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F9: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 9); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F10: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 10); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F11: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 11); |
buf = count = 0; |
return 1; |
case MSIM_KEY_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) != (MSIM_KEY_F1 & 0xff)) { |
keybuffer_push(keybuffer, buf); |
buf = count = 0; |
return 1; |
} |
if (count <= 1) |
return 1; |
if ((buf & 0xffff) != (MSIM_KEY_F1 & 0xffff) |
&& (buf & 0xffff) != (MSIM_KEY_F5 & 0xffff) ) { |
keybuffer_push(keybuffer, buf & 0xff); |
keybuffer_push(keybuffer, (buf >> 8) &0xff); |
buf = count = 0; |
return 1; |
} |
if (count <= 2) |
return 1; |
switch (buf) { |
case MSIM_KEY_F1: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 1); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F2: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 2); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F3: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 3); |
buf = count = 0; |
return 1; |
case MSIM_KEY_F4: |
keybuffer_push(keybuffer,FUNCTION_KEYS | 4); |
buf = count = 0; |
return 1; |
} |
if((buf & 0xffffff) != (MSIM_KEY_F5 & 0xffffff) |
&& (buf & 0xffffff) != (MSIM_KEY_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 MSIM_KEY_F5: |
case MSIM_KEY_F6: |
case MSIM_KEY_F7: |
case MSIM_KEY_F8: |
case MSIM_KEY_F9: |
case MSIM_KEY_F10: |
case MSIM_KEY_F11: |
case MSIM_KEY_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; |
} |
static int kbd_arch_process_fb(keybuffer_t *keybuffer, int scan_code) |
{ |
static unsigned long buf = 0; |
371,7 → 232,7 |
if (fb_fb) |
return kbd_arch_process_fb(keybuffer, scan_code); |
return kbd_arch_process_no_fb(keybuffer, scan_code); |
return kbd_process_no_fb(keybuffer, scan_code); |
} |
/** @} |
*/ |
/branches/dynload/uspace/srv/console/console.c |
---|
327,7 → 327,6 |
break; |
case KBD_PUSHCHAR: |
/* got key from keyboard driver */ |
retval = 0; |
c = IPC_GET_ARG1(call); |
/* switch to another virtual console */ |
466,7 → 465,9 |
} |
continue; |
} |
keybuffer_pop(&conn->keybuffer, (int *) &arg1); |
int ch; |
keybuffer_pop(&conn->keybuffer, &ch); |
arg1 = ch; |
break; |
} |
ipc_answer_2(callid, EOK, arg1, arg2); |
/branches/dynload/uspace/srv/console/gcons.c |
---|
258,7 → 258,7 |
static int gcons_find_conbut(int x, int y) |
{ |
int status_start = STATUS_START + (xres - 800) / 2;; |
int status_start = STATUS_START + (xres - 800) / 2; |
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT) |
return -1; |
/branches/dynload/uspace/srv/fb/sgcn.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* 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. |
*/ |
/** @defgroup sgcnfb SGCN |
* @brief userland driver of the Serengeti console output |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SGCN_H_ |
#define FB_SGCN_H_ |
int sgcn_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/fb/serial_console.c |
---|
0,0 → 1,110 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2008 Pavel Rimsky |
* 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. |
*/ |
/** |
* @defgroup serial Serial console |
* @brief Serial console services (putc, puts, clear screen, cursor goto,...) |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include "serial_console.h" |
#define MAX_CONTROL 20 |
static uint32_t width; |
static uint32_t height; |
static putc_function_t putc_function; |
void serial_puts(char *str) |
{ |
while (*str) |
putc_function(*(str++)); |
} |
void serial_goto(const unsigned int row, const unsigned int col) |
{ |
if ((row > height) || (col > width)) |
return; |
char control[20]; |
snprintf(control, 20, "\033[%u;%uf", row + 1, col + 1); |
serial_puts(control); |
} |
void serial_clrscr(void) |
{ |
serial_puts("\033[2J"); |
} |
void serial_scroll(int i) |
{ |
if (i > 0) { |
serial_goto(height - 1, 0); |
while (i--) |
serial_puts("\033D"); |
} else if (i < 0) { |
serial_goto(0, 0); |
while (i++) |
serial_puts("\033M"); |
} |
} |
void serial_set_style(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
serial_puts(control); |
} |
void serial_cursor_disable(void) |
{ |
serial_puts("\033[?25l"); |
} |
void serial_cursor_enable(void) |
{ |
serial_puts("\033[?25h"); |
} |
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h) |
{ |
width = w; |
height = h; |
putc_function = putc_fn; |
} |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/fb/msim.c |
---|
49,6 → 49,7 |
#include <align.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "msim.h" |
#define WIDTH 80 |
66,57 → 67,6 |
*virt_addr = c; |
} |
static void msim_puts(char *str) |
{ |
while (*str) |
*virt_addr = *(str++); |
} |
static void msim_clrscr(void) |
{ |
msim_puts("\033[2J"); |
} |
static void msim_goto(const unsigned int row, const unsigned int col) |
{ |
if ((row > HEIGHT) || (col > WIDTH)) |
return; |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1); |
msim_puts(control); |
} |
static void msim_set_style(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
msim_puts(control); |
} |
static void msim_cursor_disable(void) |
{ |
msim_puts("\033[?25l"); |
} |
static void msim_cursor_enable(void) |
{ |
msim_puts("\033[?25h"); |
} |
static void msim_scroll(int i) |
{ |
if (i > 0) { |
msim_goto(HEIGHT - 1, 0); |
while (i--) |
msim_puts("\033D"); |
} else if (i < 0) { |
msim_goto(0, 0); |
while (i++) |
msim_puts("\033M"); |
} |
} |
static void msim_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
141,9 → 91,9 |
/* Clear the terminal, set scrolling region |
to 0 - 25 lines */ |
msim_clrscr(); |
msim_goto(0, 0); |
msim_puts("\033[0;25r"); |
serial_clrscr(); |
serial_goto(0, 0); |
serial_puts("\033[0;25r"); |
while (true) { |
callid = async_get_call(&call); |
157,7 → 107,7 |
newrow = IPC_GET_ARG2(call); |
newcol = IPC_GET_ARG3(call); |
if ((lastcol != newcol) || (lastrow != newrow)) |
msim_goto(newrow, newcol); |
serial_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
msim_putc(c); |
166,7 → 116,7 |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
msim_goto(newrow, newcol); |
serial_goto(newrow, newcol); |
lastrow = newrow; |
lastcol = newcol; |
retval = 0; |
175,7 → 125,7 |
ipc_answer_2(callid, EOK, HEIGHT, WIDTH); |
continue; |
case FB_CLEAR: |
msim_clrscr(); |
serial_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
182,9 → 132,9 |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
msim_set_style(0); |
serial_set_style(0); |
else |
msim_set_style(7); |
serial_set_style(7); |
retval = 0; |
break; |
case FB_SCROLL: |
193,15 → 143,15 |
retval = EINVAL; |
break; |
} |
msim_scroll(i); |
msim_goto(lastrow, lastcol); |
serial_scroll(i); |
serial_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
msim_cursor_enable(); |
serial_cursor_enable(); |
else |
msim_cursor_disable(); |
serial_cursor_disable(); |
retval = 0; |
break; |
default: |
218,6 → 168,8 |
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE); |
serial_console_init(msim_putc, WIDTH, HEIGHT); |
async_set_client_connection(msim_client_connection); |
return 0; |
} |
/branches/dynload/uspace/srv/fb/serial_console.h |
---|
0,0 → 1,52 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* 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. |
*/ |
/** |
* @defgroup serial Serial console |
* @brief Serial console services (putc, puts, clear screen, cursor goto,...) |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SERIAL_CONSOLE_H_ |
#define FB_SERIAL_CONSOLE_H_ |
typedef void (*putc_function_t)(char); |
void serial_puts(char *str); |
void serial_goto(const unsigned int row, const unsigned int col); |
void serial_clrscr(void); |
void serial_scroll(int i); |
void serial_set_style(const unsigned int mode); |
void serial_cursor_disable(void); |
void serial_cursor_enable(void); |
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h); |
#endif |
/branches/dynload/uspace/srv/fb/main.c |
---|
38,6 → 38,7 |
#include "fb.h" |
#include "ega.h" |
#include "msim.h" |
#include "sgcn.h" |
#include "main.h" |
#define NAME "fb" |
79,6 → 80,12 |
initialized = true; |
} |
#endif |
#ifdef SGCN_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 4)) { |
if (sgcn_init() == 0) |
initialized = true; |
} |
#endif |
if (!initialized) |
return -1; |
/branches/dynload/uspace/srv/fb/sgcn.c |
---|
0,0 → 1,250 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2008 Pavel Rimsky |
* 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. |
*/ |
/** @defgroup sgcnfb SGCN |
* @brief userland driver of the Serengeti console output |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <ipc/ipc.h> |
#include <ipc/fb.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <errno.h> |
#include <stdio.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "sgcn.h" |
#define WIDTH 80 |
#define HEIGHT 24 |
/** |
* Virtual address mapped to SRAM. |
*/ |
static uintptr_t sram_virt_addr; |
/** |
* SGCN buffer offset within SGCN. |
*/ |
static uintptr_t sram_buffer_offset; |
/* Allow only 1 connection */ |
static int client_connected = 0; |
/** |
* SGCN buffer header. It is placed at the very beginning of the SGCN |
* buffer. |
*/ |
typedef struct { |
/** hard-wired to "CON" */ |
char magic[4]; |
/** we don't need this */ |
char unused[24]; |
/** offset within the SGCN buffer of the output buffer start */ |
uint32_t out_begin; |
/** offset within the SGCN buffer of the output buffer end */ |
uint32_t out_end; |
/** offset within the SGCN buffer of the output buffer read pointer */ |
uint32_t out_rdptr; |
/** offset within the SGCN buffer of the output buffer write pointer */ |
uint32_t out_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the console buffer beginning. |
*/ |
#define SGCN_BUFFER(type, offset) \ |
((type *) (sram_virt_addr + sram_buffer_offset + (offset))) |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** |
* Pushes the character to the SGCN serial. |
* @param c character to be pushed |
*/ |
static void sgcn_putc(char c) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->out_begin; |
uint32_t end = SGCN_BUFFER_HEADER->out_end; |
uint32_t size = end - begin; |
/* we need pointers to volatile variables */ |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr); |
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin; |
while (*out_rdptr_ptr == new_wrptr) |
; |
*buf_ptr = c; |
*out_wrptr_ptr = new_wrptr; |
} |
/** |
* Main function of the thread serving client connections. |
*/ |
static void sgcn_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
char c; |
int lastcol = 0; |
int lastrow = 0; |
int newcol; |
int newrow; |
int fgcolor; |
int bgcolor; |
int i; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
/* Clear the terminal, set scrolling region |
to 0 - 24 lines */ |
serial_clrscr(); |
serial_goto(0, 0); |
serial_puts("\033[0;24r"); |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
ipc_answer_0(callid, EOK); |
return; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
newrow = IPC_GET_ARG2(call); |
newcol = IPC_GET_ARG3(call); |
if ((lastcol != newcol) || (lastrow != newrow)) |
serial_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
sgcn_putc(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
serial_goto(newrow, newcol); |
lastrow = newrow; |
lastcol = newcol; |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, HEIGHT, WIDTH); |
continue; |
case FB_CLEAR: |
serial_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
serial_set_style(0); |
else |
serial_set_style(7); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > HEIGHT) || (i < -HEIGHT)) { |
retval = EINVAL; |
break; |
} |
serial_scroll(i); |
serial_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
serial_cursor_enable(); |
else |
serial_cursor_disable(); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
/** |
* Initializes the SGCN serial driver. |
*/ |
int sgcn_init(void) |
{ |
sram_virt_addr = (uintptr_t) as_get_mappable_page( |
sysinfo_value("sram.area.size")); |
int result = physmem_map( |
(void *) sysinfo_value("sram.address.physical"), |
(void *) sram_virt_addr, |
sysinfo_value("sram.area.size") / PAGE_SIZE, |
AS_AREA_READ | AS_AREA_WRITE |
); |
if (result != 0) { |
printf("SGCN: uspace driver couldn't map physical memory: %d\n", |
result); |
} |
serial_console_init(sgcn_putc, WIDTH, HEIGHT); |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
async_set_client_connection(sgcn_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dynload/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/dynload/uspace/srv/fb/Makefile |
---|
56,14 → 56,24 |
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 |
endif |
ifeq ($(ARCH), mips32) |
SOURCES += msim.c |
SOURCES += msim.c \ |
serial_console.c |
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN |
endif |
ifeq ($(ARCH), sparc64) |
SOURCES += sgcn.c \ |
serial_console.c |
CFLAGS += -DSGCN_ENABLED |
endif |
CFLAGS += -D$(ARCH) |
/branches/dynload/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; |
135,7 → 137,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; |
/branches/dynload/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/dynload/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/dynload/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/dynload/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/dynload/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/dynload/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/dynload/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/dynload/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) { |
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; |
} |
static int fat_destroy(void *node) |
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; |
} |
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); |
} |
static bool fat_link(void *prnt, void *chld, const char *name) |
fat_idx_destroy(nodep->idx); |
free(nodep); |
return EOK; |
} |
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); |
static int fat_unlink(void *prnt, void *chld) |
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; |
} |
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/dynload/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) |
466,6 → 477,15 |
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); |
/* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ |
491,6 → 511,9 |
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) |
rwlock_read_unlock(&file->node->contents_rwlock); |
/branches/dynload/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/dynload/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/dynload/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; |