/branches/arm/uspace/uspace.config |
---|
File deleted |
/branches/arm/uspace/app/tetris/pathnames.h |
---|
File deleted |
/branches/arm/uspace/app/tetris/screen.c |
---|
36,7 → 36,7 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
50,22 → 50,26 |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <io/stream.h> |
#include <vfs/vfs.h> |
#include <async.h> |
#include "screen.h" |
#include "tetris.h" |
#include "../../srv/console/console.h" |
#include <io/console.h> |
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ |
#define STOP (B_COLS - 3) |
static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */ |
static int curscore; |
static int isset; /* true => terminal is in game mode */ |
static int isset; /* true => terminal is in game mode */ |
static int use_color; /* true => use colors */ |
static const struct shape *lastshape; |
/* |
* putstr() is for unpadded strings (either as in termcap(5) or |
* simply literal strings); |
* simply literal strings); |
*/ |
static inline void putstr(char *s) |
{ |
73,29 → 77,22 |
putchar(*(s++)); |
} |
static int con_phone; |
static void set_style(int fgcolor, int bgcolor) |
static void start_standout(uint32_t color) |
{ |
async_msg_2(con_phone, CONSOLE_SET_STYLE, fgcolor, bgcolor); |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, |
use_color ? color : 0x000000); |
} |
static void start_standout(void) |
{ |
set_style(0xf0f0f0, 0); |
} |
static void resume_normal(void) |
{ |
set_style(0, 0xf0f0f0); |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0, 0xf0f0f0); |
} |
void clear_screen(void) |
{ |
async_msg_0(con_phone, CONSOLE_CLEAR); |
console_clear(fphone(stdout)); |
moveto(0, 0); |
} |
102,24 → 99,20 |
/* |
* Clear the screen, forgetting the current contents in the process. |
*/ |
void |
scr_clear(void) |
void scr_clear(void) |
{ |
resume_normal(); |
async_msg_0(con_phone, CONSOLE_CLEAR); |
console_clear(fphone(stdout)); |
curscore = -1; |
memset((char *)curscreen, 0, sizeof(curscreen)); |
memset(curscreen, 0, sizeof(curscreen)); |
} |
/* |
* Set up screen |
*/ |
void |
scr_init(void) |
void scr_init(void) |
{ |
con_phone = get_cons_phone(); |
async_msg_1(con_phone, CONSOLE_CURSOR_VISIBILITY, 0); |
console_cursor_visibility(fphone(stdout), 0); |
resume_normal(); |
scr_clear(); |
} |
126,38 → 119,49 |
void moveto(int r, int c) |
{ |
async_msg_2(con_phone, CONSOLE_GOTO, r, c); |
fflush(stdout); |
console_goto(fphone(stdout), c, r); |
} |
static void fflush(void) |
{ |
async_msg_0(con_phone, CONSOLE_FLUSH); |
} |
winsize_t winsize; |
static int get_display_size(winsize_t *ws) |
{ |
return async_req_0_2(con_phone, CONSOLE_GETSIZE, &ws->ws_row, |
&ws->ws_col); |
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row); |
} |
static int get_display_color_sup(void) |
{ |
int rc; |
int ccap; |
rc = console_get_color_cap(fphone(stdout), &ccap); |
if (rc != 0) |
return 0; |
return (ccap >= CONSOLE_CCAP_RGB); |
} |
/* |
* Set up screen mode. |
*/ |
void |
scr_set(void) |
void scr_set(void) |
{ |
winsize_t ws; |
Rows = 0, Cols = 0; |
Rows = 0; |
Cols = 0; |
if (get_display_size(&ws) == 0) { |
Rows = ws.ws_row; |
Cols = ws.ws_col; |
} |
if (Rows < MINROWS || Cols < MINCOLS) { |
use_color = get_display_color_sup(); |
if ((Rows < MINROWS) || (Cols < MINCOLS)) { |
char smallscr[55]; |
snprintf(smallscr, sizeof(smallscr), |
"the screen is too small (must be at least %dx%d)", |
MINROWS, MINCOLS); |
164,7 → 168,7 |
stop(smallscr); |
} |
isset = 1; |
scr_clear(); |
} |
171,76 → 175,80 |
/* |
* End screen mode. |
*/ |
void |
scr_end(void) |
void scr_end(void) |
{ |
console_cursor_visibility(fphone(stdout), 1); |
} |
void |
stop(char *why) |
void stop(char *why) |
{ |
if (isset) |
scr_end(); |
errx(1, "aborting: %s", why); |
} |
/* |
* Update the screen. |
*/ |
void |
scr_update(void) |
void scr_update(void) |
{ |
cell *bp, *sp; |
cell so, cur_so = 0; |
int i, ccol, j; |
static const struct shape *lastshape; |
/* always leave cursor after last displayed point */ |
cell *bp; |
cell *sp; |
cell so; |
cell cur_so = 0; |
int i; |
int j; |
int ccol; |
/* Always leave cursor after last displayed point */ |
curscreen[D_LAST * B_COLS - 1] = -1; |
if (score != curscore) { |
moveto(0, 0); |
printf("Score: %d", score); |
curscore = score; |
} |
/* draw preview of next pattern */ |
if (showpreview && (nextshape != lastshape)) { |
/* Draw preview of next pattern */ |
if ((showpreview) && (nextshape != lastshape)) { |
int i; |
static int r=5, c=2; |
static int r = 5, c = 2; |
int tr, tc, t; |
lastshape = nextshape; |
/* clean */ |
/* Clean */ |
resume_normal(); |
moveto(r-1, c-1); putstr(" "); |
moveto(r, c-1); putstr(" "); |
moveto(r+1, c-1); putstr(" "); |
moveto(r+2, c-1); putstr(" "); |
moveto(r-3, c-2); |
moveto(r - 1, c - 1); |
putstr(" "); |
moveto(r, c - 1); |
putstr(" "); |
moveto(r + 1, c - 1); |
putstr(" "); |
moveto(r + 2, c - 1); |
putstr(" "); |
moveto(r - 3, c - 2); |
putstr("Next shape:"); |
/* draw */ |
start_standout(); |
/* Draw */ |
start_standout(nextshape->color); |
moveto(r, 2 * c); |
putstr(" "); |
for (i = 0; i < 3; i++) { |
t = c + r * B_COLS; |
t += nextshape->off[i]; |
tr = t / B_COLS; |
tc = t % B_COLS; |
moveto(tr, 2*tc); |
putstr(" "); |
} |
resume_normal(); |
} |
bp = &board[D_FIRST * B_COLS]; |
sp = &curscreen[D_FIRST * B_COLS]; |
for (j = D_FIRST; j < D_LAST; j++) { |
248,6 → 256,7 |
for (i = 0; i < B_COLS; bp++, sp++, i++) { |
if (*sp == (so = *bp)) |
continue; |
*sp = so; |
if (i != ccol) { |
if (cur_so) { |
256,15 → 265,16 |
} |
moveto(RTOD(j), CTOD(i)); |
} |
if (so != cur_so) { |
if (so) |
start_standout(); |
start_standout(so); |
else |
resume_normal(); |
cur_so = so; |
} |
putstr(" "); |
ccol = i + 1; |
/* |
* Look ahead a bit, to avoid extra motion if |
274,33 → 284,35 |
* `unnecessarily'. Skip it all, though, if |
* the next cell is a different color. |
*/ |
#define STOP (B_COLS - 3) |
if (i > STOP || sp[1] != bp[1] || so != bp[1]) |
if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1])) |
continue; |
if (sp[2] != bp[2]) |
sp[1] = -1; |
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) { |
else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) { |
sp[2] = -1; |
sp[1] = -1; |
} |
} |
} |
if (cur_so) |
resume_normal(); |
fflush(); |
fflush(stdout); |
} |
/* |
* Write a message (set!=0), or clear the same message (set==0). |
* Write a message (set != 0), or clear the same message (set == 0). |
* (We need its length in case we have to overwrite with blanks.) |
*/ |
void |
scr_msg(char *s, int set) |
void scr_msg(char *s, int set) |
{ |
int l = str_size(s); |
int l = strlen(s); |
moveto(Rows - 2, ((Cols - l) >> 1) - 1); |
moveto(Rows - 2, ((Cols - l) >> 1) - 1); |
if (set) |
putstr(s); |
else |
310,4 → 322,3 |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/scores.c |
---|
36,7 → 36,7 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
48,21 → 48,18 |
* |
* Major whacks since then. |
*/ |
#include <errno.h> |
/* #include <err.h> */ |
/* #include <fcntl.h> */ |
/* #include <pwd.h> */ |
#include <stdio.h> |
/* #include <stdlib.h> */ |
#include <string.h> |
/* #include <time.h> */ |
/* #include <term.h> */ |
/* #include <unistd.h> */ |
/* #include <sys/param.h> */ |
/* #include <sys/stat.h> */ |
/* #include <sys/types.h> */ |
#include <io/console.h> |
#include <io/keycode.h> |
#include <vfs/vfs.h> |
#include <stdlib.h> |
#include <fcntl.h> |
#include <err.h> |
#include <time.h> |
#include "pathnames.h" |
#include "screen.h" |
#include "tetris.h" |
#include "scores.h" |
75,20 → 72,22 |
* As long as the scores are kept sorted, this is simply the first one at |
* that level. |
*/ |
#define NUMSPOTS (MAXHISCORES + 1) |
#define NLEVELS (MAXLEVEL + 1) |
/* static time_t now; */ |
/* static int nscores; */ |
/* static int gotscores; */ |
/* static struct highscore scores[NUMSPOTS]; */ |
#define NUMSPOTS (MAXHISCORES + 1) |
#define NLEVELS (MAXLEVEL + 1) |
static struct highscore scores[NUMSPOTS]; |
/* static int checkscores(struct highscore *, int); */ |
/* static int cmpscores(const void *, const void *); */ |
/* static void getscores(FILE **); */ |
/* static void printem(int, int, struct highscore *, int, const char *); */ |
/* static char *thisuser(void); */ |
/** Copy from hiscore table score with index src to dest |
* |
*/ |
static void copyhiscore(int dest, int src) |
{ |
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, |
scores[src].hs_name); |
scores[dest].hs_score = scores[src].hs_score; |
scores[dest].hs_level = scores[src].hs_level; |
} |
void showscores(int firstgame) |
{ |
98,446 → 97,137 |
moveto(10, 0); |
printf("\tRank \tLevel \tName\t points\n"); |
printf("\t========================================================\n"); |
for (i = 0; i < NUMSPOTS - 1; i++) { |
printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score); |
} |
for (i = 0; i < NUMSPOTS - 1; i++) |
printf("\t%6d %6d %-16s %20d\n", |
i + 1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score); |
if (!firstgame) { |
printf("\t========================================================\n"); |
printf("\t Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score); |
printf("\t Last %6d %-16s %20d\n", |
scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score); |
} |
printf("\n\n\n\n\tPress any key to return to main menu."); |
getchar(); |
} |
/** Copy from hiscore table score with index src to dest |
* |
*/ |
static void copyhiscore(int dest, int src) |
{ |
strcpy(scores[dest].hs_name, scores[src].hs_name); |
scores[dest].hs_score = scores[src].hs_score; |
scores[dest].hs_level = scores[src].hs_level; |
} |
void insertscore(int score, int level) |
{ |
int i,j; |
int key; |
int i; |
int j; |
size_t off; |
console_event_t ev; |
clear_screen(); |
moveto(10 , 10); |
moveto(10, 10); |
puts("Insert your name: "); |
strncpy(scores[NUMSPOTS - 1].hs_name, "Player", MAXLOGNAME); |
str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, |
"Player"); |
i = 6; |
off = 6; |
moveto(10 , 28); |
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................"); |
key = getchar(); |
while(key != '\n') { |
if (key == '\b') { |
if (i > 0) |
scores[NUMSPOTS - 1].hs_name[--i] = '\0'; |
} else { |
if (i < (MAXLOGNAME - 1)) |
scores[NUMSPOTS - 1].hs_name[i++] = key; |
scores[NUMSPOTS - 1].hs_name[i] = '\0'; |
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME-i, |
"........................................"); |
while (1) { |
fflush(stdout); |
if (!console_get_event(fphone(stdin), &ev)) |
exit(1); |
if (ev.type == KEY_RELEASE) |
continue; |
if (ev.key == KC_ENTER || ev.key == KC_NENTER) |
break; |
if (ev.key == KC_BACKSPACE) { |
if (i > 0) { |
wchar_t uc; |
--i; |
while (off > 0) { |
--off; |
size_t otmp = off; |
uc = str_decode(scores[NUMSPOTS - 1].hs_name, |
&otmp, STR_BOUNDS(MAXLOGNAME) + 1); |
if (uc != U_SPECIAL) |
break; |
} |
scores[NUMSPOTS - 1].hs_name[off] = '\0'; |
} |
} else if (ev.c != '\0') { |
if (i < (MAXLOGNAME - 1)) { |
if (chr_encode(ev.c, scores[NUMSPOTS - 1].hs_name, |
&off, STR_BOUNDS(MAXLOGNAME) + 1) == EOK) { |
++i; |
} |
scores[NUMSPOTS - 1].hs_name[off] = '\0'; |
} |
} |
moveto(10 , 28); |
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................"); |
key = getchar(); |
moveto(10, 28); |
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i, |
"........................................"); |
} |
scores[NUMSPOTS - 1].hs_score = score; |
scores[NUMSPOTS - 1].hs_score = score; |
scores[NUMSPOTS - 1].hs_level = level; |
i = NUMSPOTS-1; |
i = NUMSPOTS - 1; |
while ((i > 0) && (scores[i - 1].hs_score < score)) |
i--; |
for (j = NUMSPOTS - 2; j > i; j--) { |
copyhiscore(j,j-1); |
} |
copyhiscore(i, NUMSPOTS - 1); |
for (j = NUMSPOTS - 2; j > i; j--) |
copyhiscore(j, j-1); |
copyhiscore(i, NUMSPOTS - 1); |
} |
void initscores(void) |
{ |
int i; |
for(i = 0; i < NUMSPOTS; i++) { |
strncpy(scores[i].hs_name, "HelenOS Team", MAXLOGNAME); |
scores[i].hs_score = (NUMSPOTS - i) * 200; |
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1); |
for (i = 0; i < NUMSPOTS; i++) { |
str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team"); |
scores[i].hs_score = (NUMSPOTS - i) * 200; |
scores[i].hs_level = (i + 1 > MAXLEVEL ? MAXLEVEL : i + 1); |
} |
} |
/* |
* Read the score file. Can be called from savescore (before showscores) |
* or showscores (if savescore will not be called). If the given pointer |
* is not NULL, sets *fpp to an open file pointer that corresponds to a |
* read/write score file that is locked with LOCK_EX. Otherwise, the |
* file is locked with LOCK_SH for the read and closed before return. |
* |
* Note, we assume closing the stdio file releases the lock. |
*/ |
/* static void */ |
/* getscores(FILE **fpp) */ |
/* { */ |
/* int sd, mint, lck, mask, i; */ |
/* char *mstr, *human; */ |
/* FILE *sf; */ |
int loadscores(void) |
{ |
FILE *f; |
size_t cnt; |
int rc; |
/* if (fpp != NULL) { */ |
/* mint = O_RDWR | O_CREAT; */ |
/* mstr = "r+"; */ |
/* human = "read/write"; */ |
/* lck = LOCK_EX; */ |
/* } else { */ |
/* mint = O_RDONLY; */ |
/* mstr = "r"; */ |
/* human = "reading"; */ |
/* lck = LOCK_SH; */ |
/* } */ |
/* setegid(egid); */ |
/* mask = umask(S_IWOTH); */ |
/* sd = open(_PATH_SCOREFILE, mint, 0666); */ |
/* (void)umask(mask); */ |
/* setegid(gid); */ |
/* if (sd < 0) { */ |
/* if (fpp == NULL) { */ |
/* nscores = 0; */ |
/* return; */ |
/* } */ |
/* err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */ |
/* } */ |
/* setegid(egid); */ |
/* if ((sf = fdopen(sd, mstr)) == NULL) */ |
/* err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */ |
/* setegid(gid); */ |
f = fopen("/data/tetris.sco", "rb"); |
if (f == NULL) |
return ENOENT; |
/* /\* */ |
/* * Grab a lock. */ |
/* *\/ */ |
/* if (flock(sd, lck)) */ |
/* warn("warning: score file %s cannot be locked", */ |
/* _PATH_SCOREFILE); */ |
cnt = fread(scores, sizeof(struct highscore), NUMSPOTS, f); |
rc = fclose(f); |
/* nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */ |
/* if (ferror(sf)) */ |
/* err(1, "error reading %s", _PATH_SCOREFILE); */ |
/* for (i = 0; i < nscores; i++) */ |
/* if (scores[i].hs_level < MINLEVEL || */ |
/* scores[i].hs_level > MAXLEVEL) */ |
/* errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */ |
if (cnt != NUMSPOTS || rc != 0) |
return EIO; |
/* if (fpp) */ |
/* *fpp = sf; */ |
/* else */ |
/* (void)fclose(sf); */ |
/* } */ |
return EOK; |
} |
void |
savescore(int level) |
void savescores(void) |
{ |
return; |
} |
/* struct highscore *sp; */ |
/* int i; */ |
/* int change; */ |
/* FILE *sf; */ |
/* const char *me; */ |
FILE *f; |
size_t cnt; |
int rc; |
/* getscores(&sf); */ |
/* gotscores = 1; */ |
/* (void)time(&now); */ |
f = fopen("/data/tetris.sco", "wb"); |
cnt = fwrite(scores, sizeof(struct highscore), NUMSPOTS, f); |
rc = fclose(f); |
/* /\* */ |
/* * Allow at most one score per person per level -- see if we */ |
/* * can replace an existing score, or (easiest) do nothing. */ |
/* * Otherwise add new score at end (there is always room). */ |
/* *\/ */ |
/* change = 0; */ |
/* me = thisuser(); */ |
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */ |
/* if (sp->hs_level != level || strcmp(sp->hs_name, me) != 0) */ |
/* continue; */ |
/* if (score > sp->hs_score) { */ |
/* (void)printf("%s bettered %s %d score of %d!\n", */ |
/* "\nYou", "your old level", level, */ |
/* sp->hs_score * sp->hs_level); */ |
/* sp->hs_score = score; /\* new score *\/ */ |
/* sp->hs_time = now; /\* and time *\/ */ |
/* change = 1; */ |
/* } else if (score == sp->hs_score) { */ |
/* (void)printf("%s tied %s %d high score.\n", */ |
/* "\nYou", "your old level", level); */ |
/* sp->hs_time = now; /\* renew it *\/ */ |
/* change = 1; /\* gotta rewrite, sigh *\/ */ |
/* } /\* else new score < old score: do nothing *\/ */ |
/* break; */ |
/* } */ |
/* if (i >= nscores) { */ |
/* strlcpy(sp->hs_name, me, sizeof sp->hs_name); */ |
/* sp->hs_level = level; */ |
/* sp->hs_score = score; */ |
/* sp->hs_time = now; */ |
/* nscores++; */ |
/* change = 1; */ |
/* } */ |
/* if (change) { */ |
/* /\* */ |
/* * Sort & clean the scores, then rewrite. */ |
/* *\/ */ |
/* nscores = checkscores(scores, nscores); */ |
/* rewind(sf); */ |
/* if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */ |
/* fflush(sf) == EOF) */ |
/* warnx("error writing %s: %s\n\t-- %s", */ |
/* _PATH_SCOREFILE, strerror(errno), */ |
/* "high scores may be damaged"); */ |
/* } */ |
/* (void)fclose(sf); /\* releases lock *\/ */ |
/* } */ |
/* |
* Get login name, or if that fails, get something suitable. |
* The result is always trimmed to fit in a score. |
*/ |
/* static char * */ |
/* thisuser(void) */ |
/* { */ |
/* const char *p; */ |
/* struct passwd *pw; */ |
/* static char u[sizeof(scores[0].hs_name)]; */ |
/* if (u[0]) */ |
/* return (u); */ |
/* p = getlogin(); */ |
/* if (p == NULL || *p == '\0') { */ |
/* pw = getpwuid(getuid()); */ |
/* if (pw != NULL) */ |
/* p = pw->pw_name; */ |
/* else */ |
/* p = " ???"; */ |
/* } */ |
/* strlcpy(u, p, sizeof(u)); */ |
/* return (u); */ |
/* } */ |
/* |
* Score comparison function for qsort. |
* |
* If two scores are equal, the person who had the score first is |
* listed first in the highscore file. |
*/ |
/* static int */ |
/* cmpscores(const void *x, const void *y) */ |
/* { */ |
/* const struct highscore *a, *b; */ |
/* long l; */ |
/* a = x; */ |
/* b = y; */ |
/* l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */ |
/* if (l < 0) */ |
/* return (-1); */ |
/* if (l > 0) */ |
/* return (1); */ |
/* if (a->hs_time < b->hs_time) */ |
/* return (-1); */ |
/* if (a->hs_time > b->hs_time) */ |
/* return (1); */ |
/* return (0); */ |
/* } */ |
/* |
* If we've added a score to the file, we need to check the file and ensure |
* that this player has only a few entries. The number of entries is |
* controlled by MAXSCORES, and is to ensure that the highscore file is not |
* monopolised by just a few people. People who no longer have accounts are |
* only allowed the highest score. Scores older than EXPIRATION seconds are |
* removed, unless they are someone's personal best. |
* Caveat: the highest score on each level is always kept. |
*/ |
/* static int */ |
/* checkscores(struct highscore *hs, int num) */ |
/* { */ |
/* struct highscore *sp; */ |
/* int i, j, k, numnames; */ |
/* int levelfound[NLEVELS]; */ |
/* struct peruser { */ |
/* char *name; */ |
/* int times; */ |
/* } count[NUMSPOTS]; */ |
/* struct peruser *pu; */ |
/* /\* */ |
/* * Sort so that highest totals come first. */ |
/* * */ |
/* * levelfound[i] becomes set when the first high score for that */ |
/* * level is encountered. By definition this is the highest score. */ |
/* *\/ */ |
/* qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */ |
/* for (i = MINLEVEL; i < NLEVELS; i++) */ |
/* levelfound[i] = 0; */ |
/* numnames = 0; */ |
/* for (i = 0, sp = hs; i < num;) { */ |
/* /\* */ |
/* * This is O(n^2), but do you think we care? */ |
/* *\/ */ |
/* for (j = 0, pu = count; j < numnames; j++, pu++) */ |
/* if (strcmp(sp->hs_name, pu->name) == 0) */ |
/* break; */ |
/* if (j == numnames) { */ |
/* /\* */ |
/* * Add new user, set per-user count to 1. */ |
/* *\/ */ |
/* pu->name = sp->hs_name; */ |
/* pu->times = 1; */ |
/* numnames++; */ |
/* } else { */ |
/* /\* */ |
/* * Two ways to keep this score: */ |
/* * - Not too many (per user), still has acct, & */ |
/* * score not dated; or */ |
/* * - High score on this level. */ |
/* *\/ */ |
/* if ((pu->times < MAXSCORES && */ |
/* getpwnam(sp->hs_name) != NULL && */ |
/* sp->hs_time + EXPIRATION >= now) || */ |
/* levelfound[sp->hs_level] == 0) */ |
/* pu->times++; */ |
/* else { */ |
/* /\* */ |
/* * Delete this score, do not count it, */ |
/* * do not pass go, do not collect $200. */ |
/* *\/ */ |
/* num--; */ |
/* for (k = i; k < num; k++) */ |
/* hs[k] = hs[k + 1]; */ |
/* continue; */ |
/* } */ |
/* } */ |
/* levelfound[sp->hs_level] = 1; */ |
/* i++, sp++; */ |
/* } */ |
/* return (num > MAXHISCORES ? MAXHISCORES : num); */ |
/* } */ |
/* |
* Show current scores. This must be called after savescore, if |
* savescore is called at all, for two reasons: |
* - Showscores munches the time field. |
* - Even if that were not the case, a new score must be recorded |
* before it can be shown anyway. |
*/ |
/* |
void |
showscores(int level) |
{ |
return; |
if (cnt != NUMSPOTS || rc != 0) |
printf("Error saving score table\n"); |
} |
*/ |
/* struct highscore *sp; */ |
/* int i, n, c; */ |
/* const char *me; */ |
/* int levelfound[NLEVELS]; */ |
/* if (!gotscores) */ |
/* getscores((FILE **)NULL); */ |
/* (void)printf("\n\t\t Tetris High Scores\n"); */ |
/* /\* */ |
/* * If level == 0, the person has not played a game but just asked for */ |
/* * the high scores; we do not need to check for printing in highlight */ |
/* * mode. If SOstr is null, we can't do highlighting anyway. */ |
/* *\/ */ |
/* me = level && SOstr ? thisuser() : NULL; */ |
/* /\* */ |
/* * Set times to 0 except for high score on each level. */ |
/* *\/ */ |
/* for (i = MINLEVEL; i < NLEVELS; i++) */ |
/* levelfound[i] = 0; */ |
/* for (i = 0, sp = scores; i < nscores; i++, sp++) { */ |
/* if (levelfound[sp->hs_level]) */ |
/* sp->hs_time = 0; */ |
/* else { */ |
/* sp->hs_time = 1; */ |
/* levelfound[sp->hs_level] = 1; */ |
/* } */ |
/* } */ |
/* /\* */ |
/* * Page each screenful of scores. */ |
/* *\/ */ |
/* for (i = 0, sp = scores; i < nscores; sp += n) { */ |
/* n = 20; */ |
/* if (i + n > nscores) */ |
/* n = nscores - i; */ |
/* printem(level, i + 1, sp, n, me); */ |
/* if ((i += n) < nscores) { */ |
/* (void)printf("\nHit RETURN to continue."); */ |
/* (void)fflush(stdout); */ |
/* while ((c = getchar()) != '\n') */ |
/* if (c == EOF) */ |
/* break; */ |
/* (void)printf("\n"); */ |
/* } */ |
/* } */ |
/* if (nscores == 0) */ |
/* printf("\t\t\t - none to date.\n"); */ |
/* } */ |
/* static void */ |
/* printem(int level, int offset, struct highscore *hs, int n, const char *me) */ |
/* { */ |
/* struct highscore *sp; */ |
/* int row, highlight, i; */ |
/* char buf[100]; */ |
/* #define TITLE "Rank Score Name (points/level)" */ |
/* #define TITL2 "==========================================================" */ |
/* printf("%s\n%s\n", TITLE, TITL2); */ |
/* highlight = 0; */ |
/* for (row = 0; row < n; row++) { */ |
/* sp = &hs[row]; */ |
/* (void)snprintf(buf, sizeof(buf), */ |
/* "%3d%c %6d %-31s (%6d on %d)\n", */ |
/* row + offset, sp->hs_time ? '*' : ' ', */ |
/* sp->hs_score * sp->hs_level, */ |
/* sp->hs_name, sp->hs_score, sp->hs_level); */ |
/* /\* Print leaders every three lines *\/ */ |
/* if ((row + 1) % 3 == 0) { */ |
/* for (i = 0; i < sizeof(buf); i++) */ |
/* if (buf[i] == ' ') */ |
/* buf[i] = '_'; */ |
/* } */ |
/* /\* */ |
/* * Highlight if appropriate. This works because */ |
/* * we only get one score per level. */ |
/* *\/ */ |
/* if (me != NULL && */ |
/* sp->hs_level == level && */ |
/* sp->hs_score == score && */ |
/* strcmp(sp->hs_name, me) == 0) { */ |
/* putpad(SOstr); */ |
/* highlight = 1; */ |
/* } */ |
/* (void)printf("%s", buf); */ |
/* if (highlight) { */ |
/* putpad(SEstr); */ |
/* highlight = 0; */ |
/* } */ |
/* } */ |
/* } */ |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/scores.h |
---|
34,8 → 34,9 |
* |
* @(#)scores.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
44,24 → 45,27 |
/* |
* Tetris scores. |
*/ |
#include <sys/time.h> |
#define MAXLOGNAME 16 |
#include <string.h> |
#define MAXLOGNAME 16 |
#define MAXHISCORES 10 |
#define MAXSCORES 9 /* maximum high score entries per person */ |
#define EXPIRATION (5L * 365 * 24 * 60 * 60) |
struct highscore { |
char hs_name[MAXLOGNAME + 1]; /* login name */ |
int hs_score; /* raw score */ |
int hs_level; /* play level */ |
// time_t hs_time; /* time at game end */ |
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */ |
int hs_score; /* raw score */ |
int hs_level; /* play level */ |
time_t hs_time; /* time at game end */ |
}; |
#define MAXHISCORES 10 |
//#define MAXSCORES 9 /* maximum high score entries per person */ |
//#define EXPIRATION (5L * 365 * 24 * 60 * 60) |
extern void showscores(int); |
extern void initscores(void); |
extern void insertscore(int score, int level); |
extern int loadscores(void); |
extern void savescores(void); |
void savescore(int); |
void showscores(int); |
void insertscore(int score, int level); |
void initscores(void); |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/tetris.c |
---|
36,30 → 36,25 |
*/ |
/** @addtogroup tetris Tetris |
* @brief Tetris ported from OpenBSD |
* @{ |
* @brief Tetris ported from OpenBSD |
* @{ |
*/ |
/** @file |
*/ |
#ifndef lint |
static const char copyright[] = |
"@(#) Copyright (c) 1992, 1993\n\ |
The Regents of the University of California. All rights reserved.\n"; |
#endif /* not lint */ |
"@(#) Copyright (c) 1992, 1993\n" |
"\tThe Regents of the University of California. All rights reserved.\n"; |
/* |
* Tetris (or however it is spelled). |
*/ |
#include <sys/time.h> |
#include <sys/types.h> |
#include <err.h> |
#include <errno.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <getopt.h> |
#include "input.h" |
#include "scores.h" |
66,66 → 61,76 |
#include "screen.h" |
#include "tetris.h" |
cell board[B_SIZE]; |
int Rows, Cols; |
cell board[B_SIZE]; |
int Rows; |
int Cols; |
const struct shape *curshape; |
const struct shape *nextshape; |
long fallrate; |
int score; |
//gid_t gid, egid; |
char key_msg[100]; |
int showpreview, classic; |
static void elide(void); |
static void setup_board(void); |
const struct shape *randshape(void); |
void onintr(int); |
void usage(void); |
long fallrate; |
int score; |
char key_msg[100]; |
int showpreview; |
int classic; |
static void elide(void); |
static void setup_board(void); |
static const struct shape *randshape(void); |
static void usage(void); |
static int firstgame = 1; |
/* |
* Set up the initial board. The bottom display row is completely set, |
* along with another (hidden) row underneath that. Also, the left and |
* Set up the initial board. The bottom display row is completely set, |
* along with another (hidden) row underneath that. Also, the left and |
* right edges are set. |
*/ |
static void |
setup_board(void) |
static void setup_board(void) |
{ |
int i; |
cell *p; |
p = board; |
cell *p = board; |
for (i = B_SIZE; i; i--) |
*p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2; |
*p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000; |
} |
/* |
* Elide any full active rows. |
*/ |
static void |
elide(void) |
static void elide(void) |
{ |
int rows = 0; |
int i, j, base; |
int i; |
int j; |
int base; |
cell *p; |
for (i = A_FIRST; i < A_LAST; i++) { |
base = i * B_COLS + 1; |
p = &board[base]; |
for (j = B_COLS - 2; *p++ != 0;) { |
if (--j <= 0) { |
/* this row is to be elided */ |
/* This row is to be elided */ |
rows++; |
memset(&board[base], 0, B_COLS - 2); |
memset(&board[base], 0, sizeof(cell) * (B_COLS - 2)); |
scr_update(); |
tsleep(); |
while (--base != 0) |
board[base + B_COLS] = board[base]; |
scr_update(); |
tsleep(); |
break; |
} |
} |
} |
switch (rows) { |
case 1: |
score += 10; |
144,16 → 149,15 |
} |
} |
const struct shape * |
randshape(void) |
const struct shape *randshape(void) |
{ |
const struct shape *tmp; |
int i, j; |
tmp = &shapes[random() % 7]; |
j = random() % 4; |
const struct shape *tmp = &shapes[random() % 7]; |
int i; |
int j = random() % 4; |
for (i = 0; i < j; i++) |
tmp = &shapes[classic? tmp->rotc : tmp->rot]; |
tmp = &shapes[classic ? tmp->rotc : tmp->rot]; |
return (tmp); |
} |
160,7 → 164,7 |
static void srandomdev(void) |
{ |
struct timeval tv; |
gettimeofday(&tv, NULL); |
srandom(tv.tv_sec + tv.tv_usec / 100000); |
} |
167,61 → 171,43 |
static void tetris_menu_draw(int level) |
{ |
clear_screen(); |
moveto(5,10); |
puts("Tetris\n\n"); |
moveto(8,10); |
printf("Level = %d (press keys 1 - 9 to change)",level); |
moveto(9,10); |
printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off")); |
moveto(12,10); |
printf("Press 'h' to show hiscore table."); |
moveto(13,10); |
printf("Press 's' to start game."); |
moveto(14,10); |
printf("Press 'q' to quit game."); |
moveto(20,10); |
printf("In game controls:"); |
moveto(21,0); |
puts(key_msg); |
clear_screen(); |
moveto(5, 10); |
puts("Tetris\n\n"); |
moveto(8, 10); |
printf("Level = %d (press keys 1 - 9 to change)", level); |
moveto(9, 10); |
printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off")); |
moveto(12, 10); |
printf("Press 'h' to show hiscore table."); |
moveto(13, 10); |
printf("Press 's' to start game."); |
moveto(14, 10); |
printf("Press 'q' to quit game."); |
moveto(20, 10); |
printf("In game controls:"); |
moveto(21, 0); |
puts(key_msg); |
} |
static int tetris_menu(int *level) |
static int tetris_menu(int *level) |
{ |
static int firstgame = 1; |
int i; |
/* if (showpreview == 0) |
(void)printf("Your score: %d point%s x level %d = %d\n", |
score, score == 1 ? "" : "s", level, score * level); |
else { |
(void)printf("Your score: %d point%s x level %d x preview penalty %0.3f = %d\n", |
score, score == 1 ? "" : "s", level, (double)PRE_PENALTY, |
(int)(score * level * PRE_PENALTY)); |
score = score * PRE_PENALTY; |
} |
savescore(level); |
showscores(level); |
printf("\nHit 's' to new game, 'q' to quit.\n"); |
*/ |
tetris_menu_draw(*level); |
while (1) { |
i = getchar(); |
int i = getchar(); |
switch(i) { |
case 'p': |
showpreview = !showpreview; |
moveto(9,21); |
moveto(9, 21); |
if (showpreview) |
printf("on "); |
else |
printf("off"); |
break; |
case 'h': |
loadscores(); |
showscores(firstgame); |
tetris_menu_draw(*level); |
break; |
235,112 → 221,103 |
case '3': |
case '4': |
case '5': |
case '6': |
case '6': |
case '7': |
case '8': |
case '9': |
*level = i - '0'; |
moveto(8,18); |
moveto(8, 18); |
printf("%d", *level); |
break; |
} |
} |
} |
int |
main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
{ |
int pos, c; |
int pos; |
int c; |
char *keys; |
int level = 2; |
char key_write[6][10]; |
int i, j; |
int i; |
int j; |
int ch; |
keys = "jkl pq"; |
// gid = getgid(); |
// egid = getegid(); |
// setegid(gid); |
classic = 0; |
showpreview = 1; |
/* while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */ |
/* switch(ch) { */ |
/* case 'c': */ |
/* /\* */ |
/* * this means: */ |
/* * - rotate the other way; */ |
/* * - no reverse video. */ |
/* *\/ */ |
/* classic = 1; */ |
/* break; */ |
/* case 'k': */ |
/* if (strlen(keys = optarg) != 6) */ |
/* usage(); */ |
/* break; */ |
/* case 'l': */ |
/* level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */ |
/* &errstr); */ |
/* if (errstr) */ |
/* errx(1, "level must be from %d to %d", */ |
/* MINLEVEL, MAXLEVEL); */ |
/* break; */ |
/* case 'p': */ |
/* showpreview = 1; */ |
/* break; */ |
/* case 's': */ |
/* showscores(0); */ |
/* exit(0); */ |
/* default: */ |
/* usage(); */ |
/* } */ |
/* argc -= optind; */ |
/* argv += optind; */ |
/* if (argc) */ |
/* usage(); */ |
while ((ch = getopt(argc, argv, "ck:ps")) != -1) |
switch(ch) { |
case 'c': |
/* |
* this means: |
* - rotate the other way |
* - no reverse video |
*/ |
classic = 1; |
break; |
case 'k': |
if (str_size(keys = optarg) != 6) |
usage(); |
break; |
case 'p': |
showpreview = 1; |
break; |
case 's': |
showscores(0); |
exit(0); |
default: |
usage(); |
} |
argc -= optind; |
argv += optind; |
if (argc) |
usage(); |
for (i = 0; i <= 5; i++) { |
for (j = i+1; j <= 5; j++) { |
for (j = i + 1; j <= 5; j++) { |
if (keys[i] == keys[j]) |
errx(1, "duplicate command keys specified."); |
} |
if (keys[i] == ' ') |
strncpy(key_write[i], "<space>", sizeof key_write[i]); |
str_cpy(key_write[i], sizeof(key_write[i]), "<space>"); |
else { |
key_write[i][0] = keys[i]; |
key_write[i][1] = '\0'; |
} |
} |
snprintf(key_msg, sizeof(key_msg), |
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit", |
key_write[0], key_write[1], key_write[2], key_write[3], |
key_write[4], key_write[5]); |
scr_init(); |
if (loadscores() != EOK) |
initscores(); |
snprintf(key_msg, sizeof key_msg, |
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit", |
key_write[0], key_write[1], key_write[2], key_write[3], |
key_write[4], key_write[5]); |
scr_init(); |
initscores(); |
while (tetris_menu(&level)) { |
fallrate = 1000000 / level; |
scr_clear(); |
setup_board(); |
srandomdev(); |
scr_set(); |
pos = A_FIRST*B_COLS + (B_COLS/2)-1; |
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1; |
nextshape = randshape(); |
curshape = randshape(); |
scr_msg(key_msg, 1); |
for (;;) { |
while (1) { |
place(curshape, pos, 1); |
scr_update(); |
place(curshape, pos, 0); |
353,7 → 330,7 |
pos += B_COLS; |
continue; |
} |
/* |
* Put up the current shape `permanently', |
* bump score, and elide any full rows. |
361,7 → 338,7 |
place(curshape, pos, 1); |
score++; |
elide(); |
/* |
* Choose a new shape. If it does not fit, |
* the game is over. |
368,12 → 345,14 |
*/ |
curshape = nextshape; |
nextshape = randshape(); |
pos = A_FIRST*B_COLS + (B_COLS/2)-1; |
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1; |
if (!fits_in(curshape, pos)) |
break; |
continue; |
} |
/* |
* Handle command keys. |
*/ |
381,22 → 360,25 |
/* quit */ |
break; |
} |
if (c == keys[4]) { |
static char msg[] = |
"paused - press RETURN to continue"; |
place(curshape, pos, 1); |
do { |
scr_update(); |
scr_msg(key_msg, 0); |
scr_msg(msg, 1); |
// (void) fflush(stdout); |
} while (rwait((struct timeval *)NULL) == -1); |
(void) fflush(stdout); |
} while (rwait((struct timeval *) NULL) == -1); |
scr_msg(msg, 0); |
scr_msg(key_msg, 1); |
place(curshape, pos, 0); |
continue; |
} |
if (c == keys[0]) { |
/* move left */ |
if (fits_in(curshape, pos - 1)) |
403,15 → 385,17 |
pos--; |
continue; |
} |
if (c == keys[1]) { |
/* turn */ |
const struct shape *new = &shapes[ |
classic? curshape->rotc : curshape->rot]; |
const struct shape *new = |
&shapes[classic ? curshape->rotc : curshape->rot]; |
if (fits_in(new, pos)) |
curshape = new; |
continue; |
} |
if (c == keys[2]) { |
/* move right */ |
if (fits_in(curshape, pos + 1)) |
418,6 → 402,7 |
pos++; |
continue; |
} |
if (c == keys[3]) { |
/* move to bottom */ |
while (fits_in(curshape, pos + B_COLS)) { |
426,6 → 411,7 |
} |
continue; |
} |
if (c == '\f') { |
scr_clear(); |
scr_msg(key_msg, 1); |
433,37 → 419,24 |
} |
scr_clear(); |
loadscores(); |
insertscore(score, level); |
score=0; |
savescores(); |
score = 0; |
} |
scr_clear(); |
printf("\n\n\n\t\tGame over.\n"); |
/* |
while ((i = getchar()) != '\n') |
if (i == EOF) |
break |
*/ |
printf("\nGame over.\n"); |
scr_end(); |
return 0; |
} |
/* void */ |
/* onintr(int signo) */ |
/* { */ |
/* scr_clear(); /\* XXX signal race *\/ */ |
/* scr_end(); /\* XXX signal race *\/ */ |
/* _exit(0); */ |
/* } */ |
void |
usage(void) |
void usage(void) |
{ |
(void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n"); |
fprintf(stderr, "usage: tetris [-ps] [-k keys]\n"); |
exit(1); |
} |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/input.c |
---|
36,7 → 36,7 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
57,7 → 57,9 |
#include "tetris.h" |
#include <async.h> |
#include "../../srv/console/console.h" |
#include <vfs/vfs.h> |
#include <io/console.h> |
#include <ipc/console.h> |
/* return true iff the given timeval is positive */ |
#define TV_POS(tv) \ |
90,14 → 92,12 |
* Return 0 => no input, 1 => can read() from stdin |
* |
*/ |
int |
rwait(struct timeval *tvp) |
int rwait(struct timeval *tvp) |
{ |
struct timeval starttv, endtv, *s; |
static ipc_call_t charcall; |
ipcarg_t rc; |
int cons_phone; |
/* |
* Someday, select() will do this for us. |
* Just in case that day is now, and no one has |
109,14 → 109,15 |
s = &endtv; |
} else |
s = NULL; |
if (!lastchar) { |
again: |
if (!getchar_inprog) { |
cons_phone = get_cons_phone(); |
getchar_inprog = async_send_2(cons_phone, |
CONSOLE_GETCHAR, 0, 0, &charcall); |
getchar_inprog = async_send_0(fphone(stdin), |
CONSOLE_GET_EVENT, &charcall); |
} |
if (!s) |
if (!s) |
async_wait_for(getchar_inprog, &rc); |
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) { |
tvp->tv_sec = 0; |
123,19 → 124,25 |
tvp->tv_usec = 0; |
return (0); |
} |
getchar_inprog = 0; |
if (rc) { |
if (rc) |
stop("end of file, help"); |
} |
lastchar = IPC_GET_ARG1(charcall); |
if (IPC_GET_ARG1(charcall) == KEY_RELEASE) |
goto again; |
lastchar = IPC_GET_ARG4(charcall); |
} |
if (tvp) { |
/* since there is input, we may not have timed out */ |
(void) gettimeofday(&endtv, NULL); |
TV_SUB(&endtv, &starttv); |
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */ |
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */ |
} |
return (1); |
return 1; |
} |
/* |
142,11 → 149,10 |
* `sleep' for the current turn time (using select). |
* Eat any input that might be available. |
*/ |
void |
tsleep(void) |
void tsleep(void) |
{ |
struct timeval tv; |
tv.tv_sec = 0; |
tv.tv_usec = fallrate; |
while (TV_POS(&tv)) |
159,12 → 165,11 |
/* |
* getchar with timeout. |
*/ |
int |
tgetchar(void) |
int tgetchar(void) |
{ |
static struct timeval timeleft; |
char c; |
/* |
* Reset timeleft to fallrate whenever it is not positive. |
* In any case, wait to see if there is any input. If so, |
175,17 → 180,18 |
* Most of the hard work is done by rwait(). |
*/ |
if (!TV_POS(&timeleft)) { |
faster(); /* go faster */ |
faster(); /* go faster */ |
timeleft.tv_sec = 0; |
timeleft.tv_usec = fallrate; |
} |
if (!rwait(&timeleft)) |
return (-1); |
return -1; |
c = lastchar; |
lastchar = '\0'; |
return ((int)(unsigned char)c); |
return ((int) (unsigned char) c); |
} |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/tetris.h |
---|
36,7 → 36,7 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
55,57 → 55,60 |
* worrying about addressing problems. |
*/ |
/* the board */ |
#define B_COLS 12 |
#define B_ROWS 23 |
#define B_SIZE (B_ROWS * B_COLS) |
/* The board */ |
#define B_COLS 12 |
#define B_ROWS 23 |
#define B_SIZE (B_ROWS * B_COLS) |
typedef unsigned char cell; |
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */ |
typedef uint32_t cell; |
/* the displayed area (rows) */ |
#define D_FIRST 1 |
#define D_LAST 22 |
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */ |
/* the active area (rows) */ |
#define A_FIRST 1 |
#define A_LAST 21 |
/* The displayed area (rows) */ |
#define D_FIRST 1 |
#define D_LAST 22 |
/* The active area (rows) */ |
#define A_FIRST 1 |
#define A_LAST 21 |
/* |
* Minimum display size. |
*/ |
#define MINROWS 23 |
#define MINCOLS 40 |
#define MINROWS 23 |
#define MINCOLS 40 |
extern int Rows, Cols; /* current screen size */ |
/* Current screen size */ |
extern int Rows; |
extern int Cols; |
/* |
* Translations from board coordinates to display coordinates. |
* As with board coordinates, display coordiates are zero origin. |
*/ |
#define RTOD(x) ((x) - 1) |
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1)) |
#define RTOD(x) ((x) - 1) |
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1)) |
/* |
* A `shape' is the fundamental thing that makes up the game. There |
* are 7 basic shapes, each consisting of four `blots': |
* |
* X.X X.X X.X |
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X |
* X X X |
* X.X X.X X.X |
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X |
* X X X |
* |
* 0 1 2 3 4 5 6 |
* 0 1 2 3 4 5 6 |
* |
* Except for 3 and 6, the center of each shape is one of the blots. |
* This blot is designated (0,0). The other three blots can then be |
* This blot is designated (0, 0). The other three blots can then be |
* described as offsets from the center. Shape 3 is the same under |
* rotation, so its center is effectively irrelevant; it has been chosen |
* so that it `sticks out' upward and leftward. Except for shape 6, |
* all the blots are contained in a box going from (-1,-1) to (+1,+1); |
* all the blots are contained in a box going from (-1, -1) to (+1, +1); |
* shape 6's center `wobbles' as it rotates, so that while it `sticks out' |
* rightward, its rotation---a vertical line---`sticks out' downward. |
* The containment box has to include the offset (2,0), making the overall |
* containment box range from offset (-1,-1) to (+2,+1). (This is why |
* The containment box has to include the offset (2, 0), making the overall |
* containment box range from offset (-1, -1) to (+2, +1). (This is why |
* there is only one row above, but two rows below, the display area.) |
* |
* The game works by choosing one of these shapes at random and putting |
116,7 → 119,7 |
* At this time, any completely filled rows are elided, and blots above |
* these rows move down to make more room. A new random shape is again |
* introduced at the top of the board, and the whole process repeats. |
* The game ends when the new shape will not fit at (1,5). |
* The game ends when the new shape will not fit at (1, 5). |
* |
* While the shapes are falling, the user can rotate them counterclockwise |
* 90 degrees (in addition to moving them left or right), provided that the |
128,9 → 131,10 |
* rotated forms. |
*/ |
struct shape { |
int rot; /* index of rotated version of this shape */ |
int rotc; /* -- " -- in classic version */ |
int off[3]; /* offsets to other blots if center is at (0,0) */ |
int rot; /* index of rotated version of this shape */ |
int rotc; /* -- " -- in classic version */ |
int off[3]; /* offsets to other blots if center is at (0,0) */ |
uint32_t color; |
}; |
extern const struct shape shapes[]; |
148,15 → 152,16 |
* The value eventually reaches a limit, and things stop going faster, |
* but by then the game is utterly impossible. |
*/ |
extern long fallrate; /* less than 1 million; smaller => faster */ |
#define faster() (fallrate -= fallrate / 3000) |
extern long fallrate; /* less than 1 million; smaller => faster */ |
#define faster() (fallrate -= fallrate / 3000) |
/* |
* Game level must be between 1 and 9. This controls the initial fall rate |
* and affects scoring. |
*/ |
#define MINLEVEL 1 |
#define MAXLEVEL 9 |
#define MINLEVEL 1 |
#define MAXLEVEL 9 |
/* |
* Scoring is as follows: |
170,19 → 175,17 |
* |
* If previewing has been turned on, the score is multiplied by PRE_PENALTY. |
*/ |
#define PRE_PENALTY 0.75 |
#define PRE_PENALTY 0.75 |
extern int score; /* the obvious thing */ |
//extern gid_t gid, egid; |
extern int score; /* The obvious thing */ |
extern char key_msg[100]; |
extern int showpreview; |
extern int classic; |
extern char key_msg[100]; |
extern int showpreview; |
extern int classic; |
int fits_in(const struct shape *, int); |
void place(const struct shape *, int, int); |
void stop(char *); |
extern int fits_in(const struct shape *, int); |
extern void place(const struct shape *, int, int); |
extern void stop(char *); |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/shapes.c |
---|
36,7 → 36,7 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
50,35 → 50,35 |
#include <unistd.h> |
#include "tetris.h" |
#define TL -B_COLS-1 /* top left */ |
#define TC -B_COLS /* top center */ |
#define TR -B_COLS+1 /* top right */ |
#define ML -1 /* middle left */ |
#define MR 1 /* middle right */ |
#define BL B_COLS-1 /* bottom left */ |
#define BC B_COLS /* bottom center */ |
#define BR B_COLS+1 /* bottom right */ |
#define TL (-B_COLS - 1) /* top left */ |
#define TC (-B_COLS) /* top center */ |
#define TR (-B_COLS + 1) /* top right */ |
#define ML -1 /* middle left */ |
#define MR 1 /* middle right */ |
#define BL (B_COLS - 1) /* bottom left */ |
#define BC B_COLS /* bottom center */ |
#define BR (B_COLS + 1) /* bottom right */ |
const struct shape shapes[] = { |
/* 0*/ { 7, 7, { TL, TC, MR } }, |
/* 1*/ { 8, 8, { TC, TR, ML } }, |
/* 2*/ { 9, 11, { ML, MR, BC } }, |
/* 3*/ { 3, 3, { TL, TC, ML } }, |
/* 4*/ { 12, 14, { ML, BL, MR } }, |
/* 5*/ { 15, 17, { ML, BR, MR } }, |
/* 6*/ { 18, 18, { ML, MR, 2 } }, /* sticks out */ |
/* 7*/ { 0, 0, { TC, ML, BL } }, |
/* 8*/ { 1, 1, { TC, MR, BR } }, |
/* 9*/ { 10, 2, { TC, MR, BC } }, |
/*10*/ { 11, 9, { TC, ML, MR } }, |
/*11*/ { 2, 10, { TC, ML, BC } }, |
/*12*/ { 13, 4, { TC, BC, BR } }, |
/*13*/ { 14, 12, { TR, ML, MR } }, |
/*14*/ { 4, 13, { TL, TC, BC } }, |
/*15*/ { 16, 5, { TR, TC, BC } }, |
/*16*/ { 17, 15, { TL, MR, ML } }, |
/*17*/ { 5, 16, { TC, BC, BL } }, |
/*18*/ { 6, 6, { TC, BC, 2*B_COLS } }/* sticks out */ |
/* 0 */ { 7, 7, { TL, TC, MR }, 0xff042d}, |
/* 1 */ { 8, 8, { TC, TR, ML }, 0xff9304}, |
/* 2 */ { 9, 11, { ML, MR, BC }, 0xbeff04}, |
/* 3 */ { 3, 3, { TL, TC, ML }, 0x63ff04}, |
/* 4 */ { 12, 14, { ML, BL, MR }, 0xce04ff}, |
/* 5 */ { 15, 17, { ML, BR, MR }, 0xff04cf}, |
/* 6 */ { 18, 18, { ML, MR, 2 }, 0x7604ff}, /* sticks out */ |
/* 7 */ { 0, 0, { TC, ML, BL }, 0xff042d}, |
/* 8 */ { 1, 1, { TC, MR, BR }, 0xff9304}, |
/* 9 */ { 10, 2, { TC, MR, BC }, 0xbeff04}, |
/* 10 */ { 11, 9, { TC, ML, MR }, 0xbeff04}, |
/* 11 */ { 2, 10, { TC, ML, BC }, 0xbeff04}, |
/* 12 */ { 13, 4, { TC, BC, BR }, 0xce04ff}, |
/* 13 */ { 14, 12, { TR, ML, MR }, 0xce04ff}, |
/* 14 */ { 4, 13, { TL, TC, BC }, 0xce04ff}, |
/* 15 */ { 16, 5, { TR, TC, BC }, 0xff04cf}, |
/* 16 */ { 17, 15, { TL, MR, ML }, 0xff04cf}, |
/* 17 */ { 5, 16, { TC, BC, BL }, 0xff04cf}, |
/* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x7604ff} /* sticks out */ |
}; |
/* |
85,14 → 85,14 |
* Return true iff the given shape fits in the given position, |
* taking the current board into account. |
*/ |
int |
fits_in(const struct shape *shape, int pos) |
int fits_in(const struct shape *shape, int pos) |
{ |
int *o = shape->off; |
if (board[pos] || board[pos + *o++] || board[pos + *o++] || |
board[pos + *o]) |
if ((board[pos]) || (board[pos + *o++]) || (board[pos + *o++]) || |
(board[pos + *o])) |
return 0; |
return 1; |
} |
100,17 → 100,15 |
* Write the given shape into the current board, turning it on |
* if `onoff' is 1, and off if `onoff' is 0. |
*/ |
void |
place(const struct shape *shape, int pos, int onoff) |
void place(const struct shape *shape, int pos, int onoff) |
{ |
int *o = shape->off; |
board[pos] = onoff; |
board[pos + *o++] = onoff; |
board[pos + *o++] = onoff; |
board[pos + *o] = onoff; |
board[pos] = onoff ? shape->color : 0x000000; |
board[pos + *o++] = onoff ? shape->color : 0x000000; |
board[pos + *o++] = onoff ? shape->color : 0x000000; |
board[pos + *o] = onoff ? shape->color : 0x000000; |
} |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/input.h |
---|
36,15 → 36,14 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
int rwait(struct timeval *); |
int tgetchar(void); |
void tsleep(void); |
extern int rwait(struct timeval *); |
extern int tgetchar(void); |
extern void tsleep(void); |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/screen.h |
---|
36,16 → 36,17 |
*/ |
/** @addtogroup tetris |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
/* |
* putpad() is for padded strings with count=1. |
* putpad() is for padded strings with count = 1. |
*/ |
#define putpad(s) tputs(s, 1, put) |
#define putpad(s) tputs(s, 1, put) |
#include <sys/types.h> |
#include <async.h> |
typedef struct { |
55,17 → 56,17 |
extern winsize_t winsize; |
void moveto(int r, int c); |
void clear_screen(void); |
extern void moveto(int r, int c); |
extern void clear_screen(void); |
int put(int); /* just calls putchar; for tputs */ |
void scr_clear(void); |
void scr_end(void); |
void scr_init(void); |
void scr_msg(char *, int); |
void scr_set(void); |
void scr_update(void); |
/* just calls putchar; for tputs */ |
extern int put(int); |
extern void scr_clear(void); |
extern void scr_end(void); |
extern void scr_init(void); |
extern void scr_msg(char *, int); |
extern void scr_set(void); |
extern void scr_update(void); |
/** @} |
*/ |
/branches/arm/uspace/app/tetris/Makefile |
---|
1,5 → 1,6 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
18,7 → 19,7 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o |
26,7 → 27,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/app/init/version.c |
---|
File deleted |
/branches/arm/uspace/app/init/version.h |
---|
File deleted |
/branches/arm/uspace/app/init/init.c |
---|
27,9 → 27,9 |
*/ |
/** @addtogroup init Init |
* @brief Init process for testing purposes. |
* @brief Init process for user space environment configuration. |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
36,46 → 36,91 |
#include <stdio.h> |
#include <unistd.h> |
#include <ipc/ipc.h> |
#include <vfs/vfs.h> |
#include <bool.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#include <task.h> |
#include <malloc.h> |
#include <macros.h> |
#include <string.h> |
#include <devmap.h> |
#include "init.h" |
#include "version.h" |
static void console_wait(void) |
static void info_print(void) |
{ |
while (get_cons_phone() < 0) |
usleep(50000); // FIXME |
printf(NAME ": HelenOS init\n"); |
} |
static bool mount_fs(const char *fstype) |
static bool mount_root(const char *fstype) |
{ |
int rc = -1; |
char *opts = ""; |
const char *root_dev = "initrd"; |
while (rc < 0) { |
rc = mount(fstype, "/", "initrd"); |
if (str_cmp(fstype, "tmpfs") == 0) |
opts = "restore"; |
int rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
printf(NAME ": Root filesystem mounted, %s at %s\n", |
fstype, root_dev); |
break; |
case EBUSY: |
printf(NAME ": Root filesystem already mounted\n"); |
return false; |
case ELIMIT: |
printf(NAME ": Unable to mount root filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (%s)\n", fstype); |
return false; |
default: |
printf(NAME ": Error mounting root filesystem (%d)\n", rc); |
return false; |
} |
return true; |
} |
switch (rc) { |
case EOK: |
printf(NAME ": Root filesystem mounted\n"); |
break; |
case EBUSY: |
printf(NAME ": Root filesystem already mounted\n"); |
break; |
case ELIMIT: |
printf(NAME ": Unable to mount root filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (%s)\n", fstype); |
return false; |
default: |
sleep(5); // FIXME |
} |
static bool mount_devfs(void) |
{ |
char null[MAX_DEVICE_NAME]; |
int null_id = devmap_null_create(); |
if (null_id == -1) { |
printf(NAME ": Unable to create null device\n"); |
return false; |
} |
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id); |
int rc = mount("devfs", "/dev", null, "", IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
printf(NAME ": Device filesystem mounted\n"); |
break; |
case EBUSY: |
printf(NAME ": Device filesystem already mounted\n"); |
devmap_null_destroy(null_id); |
return false; |
case ELIMIT: |
printf(NAME ": Unable to mount device filesystem\n"); |
devmap_null_destroy(null_id); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (devfs)\n"); |
devmap_null_destroy(null_id); |
return false; |
default: |
printf(NAME ": Error mounting device filesystem (%d)\n", rc); |
devmap_null_destroy(null_id); |
return false; |
} |
return true; |
} |
82,37 → 127,132 |
static void spawn(char *fname) |
{ |
char *argv[2]; |
struct stat s; |
if (stat(fname, &s) == ENOENT) |
return; |
printf(NAME ": Spawning %s\n", fname); |
argv[0] = fname; |
argv[1] = NULL; |
if (!task_spawn(fname, argv)) |
printf(NAME ": Error spawning %s\n", fname); |
} |
static void srv_start(char *fname) |
{ |
char *argv[2]; |
task_id_t id; |
task_exit_t texit; |
int rc, retval; |
struct stat s; |
if (stat(fname, &s) == ENOENT) |
return; |
printf(NAME ": Starting %s\n", fname); |
argv[0] = fname; |
argv[1] = NULL; |
id = task_spawn(fname, argv); |
if (!id) { |
printf(NAME ": Error spawning %s\n", fname); |
return; |
} |
if (task_spawn(fname, argv) != 0) { |
/* Success */ |
sleep(1); |
rc = task_wait(id, &texit, &retval); |
if (rc != EOK) { |
printf(NAME ": Error waiting for %s\n", fname); |
return; |
} |
if (texit != TASK_EXIT_NORMAL || retval != 0) { |
printf(NAME ": Server %s failed to start (returned %d)\n", |
fname, retval); |
} |
} |
static void getvc(char *dev, char *app) |
{ |
char *argv[4]; |
char vc[MAX_DEVICE_NAME]; |
int rc; |
snprintf(vc, MAX_DEVICE_NAME, "/dev/%s", dev); |
printf(NAME ": Spawning getvc on %s\n", vc); |
dev_handle_t handle; |
rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING); |
if (rc == EOK) { |
argv[0] = "/app/getvc"; |
argv[1] = vc; |
argv[2] = app; |
argv[3] = NULL; |
if (!task_spawn("/app/getvc", argv)) |
printf(NAME ": Error spawning getvc on %s\n", vc); |
} else { |
printf(NAME ": Error waiting on %s\n", vc); |
} |
} |
void mount_data(void) |
{ |
int rc; |
printf("Trying to mount disk0 on /data... "); |
fflush(stdout); |
rc = mount("fat", "/data", "disk0", "wtcache", 0); |
if (rc == EOK) |
printf("OK\n"); |
else |
printf("Failed\n"); |
} |
int main(int argc, char *argv[]) |
{ |
info_print(); |
sleep(5); // FIXME |
if (!mount_fs("tmpfs") && !mount_fs("fat")) { |
if (!mount_root(STRING(RDFMT))) { |
printf(NAME ": Exiting\n"); |
return -1; |
} |
// FIXME: spawn("/srv/pci"); |
spawn("/srv/devfs"); |
if (!mount_devfs()) { |
printf(NAME ": Exiting\n"); |
return -2; |
} |
spawn("/srv/fb"); |
spawn("/srv/kbd"); |
spawn("/srv/console"); |
spawn("/srv/fhc"); |
spawn("/srv/obio"); |
/* |
* Start these synchronously so that mount_data() can be |
* non-blocking. |
*/ |
srv_start("/srv/ata_bd"); |
srv_start("/srv/gxe_bd"); |
console_wait(); |
version_print(); |
mount_data(); |
spawn("/app/bdsh"); |
getvc("vc0", "/app/bdsh"); |
getvc("vc1", "/app/bdsh"); |
getvc("vc2", "/app/bdsh"); |
getvc("vc3", "/app/bdsh"); |
getvc("vc4", "/app/bdsh"); |
getvc("vc5", "/app/bdsh"); |
getvc("vc6", "/app/klog"); |
return 0; |
} |
/branches/arm/uspace/app/init/init.h |
---|
28,7 → 28,7 |
/** @addtogroup init |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
36,10 → 36,11 |
#ifndef __INIT_H__ |
#define __INIT_H__ |
#define NAME "init" |
#define NAME "init" |
#define MAX_DEVICE_NAME 32 |
#endif |
/** @} |
*/ |
/branches/arm/uspace/app/init/Makefile |
---|
26,36 → 26,22 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
## Sources |
# |
OUTPUT = init |
SOURCES = \ |
init.c \ |
version.c |
init.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
66,18 → 52,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/app/bdsh/exec.c |
---|
71,7 → 71,7 |
char *path_tok; |
char *path[PATH_MAX]; |
int n = 0, i = 0; |
size_t x = strlen(cmd) + 2; |
size_t x = str_size(cmd) + 2; |
found = (char *)malloc(PATH_MAX); |
80,18 → 80,18 |
return (char *) cmd; |
} |
path_tok = cli_strdup(PATH); |
path_tok = str_dup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = cli_strtok(path_tok, PATH_DELIM); |
path[n] = strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
if ((strlen(path[n]) + x ) > PATH_MAX) { |
if ((str_size(path[n]) + x ) > PATH_MAX) { |
cli_error(CL_ENOTSUP, |
"Segment %d of path is too large, search ends at segment %d", |
n, n-1); |
break; |
} |
path[++n] = cli_strtok(NULL, PATH_DELIM); |
path[++n] = strtok(NULL, PATH_DELIM); |
} |
/* We now have n places to look for the command */ |
112,18 → 112,27 |
unsigned int try_exec(char *cmd, char **argv) |
{ |
task_id_t tid; |
task_exit_t texit; |
char *tmp; |
int retval; |
tmp = cli_strdup(find_command(cmd)); |
tmp = str_dup(find_command(cmd)); |
free(found); |
tid = task_spawn((const char *)tmp, (const char **)argv); |
tid = task_spawn((const char *)tmp, argv); |
free(tmp); |
if (tid == 0) { |
cli_error(CL_EEXEC, "Can not spawn %s", cmd); |
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd); |
return 1; |
} else { |
return 0; |
} |
task_wait(tid, &texit, &retval); |
if (texit != TASK_EXIT_NORMAL) { |
printf("Command failed (unexpectedly terminated).\n"); |
} else if (retval != 0) { |
printf("Command failed (return value %d).\n", retval); |
} |
return 0; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/quit/quit.c |
---|
File deleted |
/branches/arm/uspace/app/bdsh/cmds/modules/quit/quit_def.h |
---|
File deleted |
/branches/arm/uspace/app/bdsh/cmds/modules/quit/entry.h |
---|
File deleted |
/branches/arm/uspace/app/bdsh/cmds/modules/quit/quit.h |
---|
File deleted |
/branches/arm/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
50,30 → 50,9 |
static char *cmdname = "ls"; |
static unsigned int ls_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return LS_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return LS_FILE; |
} |
return LS_BOGUS; |
} |
static void ls_scan_dir(const char *d, DIR *dirp) |
{ |
struct dirent *dp; |
unsigned int scope; |
char *buff; |
if (! dirp) |
90,20 → 69,7 |
/* Don't worry if inserting a double slash, this will be fixed by |
* absolutize() later with subsequent calls to open() or readdir() */ |
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_DIR: |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
* it and the time that it was scoped */ |
printf("ls: skipping bogus node %s\n", dp->d_name); |
break; |
} |
ls_print(dp->d_name, buff); |
} |
free(buff); |
111,7 → 77,7 |
return; |
} |
/* ls_print_* currently does nothing more than print the entry. |
/* ls_print currently does nothing more than print the entry. |
* in the future, we will likely pass the absolute path, and |
* some sort of ls_options structure that controls how each |
* entry is printed and what is printed about it. |
118,17 → 84,23 |
* |
* Now we just print basic DOS style lists */ |
static void ls_print_dir(const char *d) |
static void ls_print(const char *name, const char *pathname) |
{ |
printf("%-40s\t<DIR>\n", d); |
struct stat s; |
int rc; |
return; |
} |
if (rc = stat(pathname, &s)) { |
/* Odd chance it was deleted from the time readdir() found it */ |
printf("ls: skipping bogus node %s\n", pathname); |
printf("rc=%d\n", rc); |
return; |
} |
if (s.is_file) |
printf("%-40s\t%llu\n", name, (long long) s.size); |
else |
printf("%-40s\n", name); |
static void ls_print_file(const char *f) |
{ |
printf("%-40s\n", f); |
return; |
} |
148,7 → 120,7 |
int cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
struct stat s; |
char *buff; |
DIR *dirp; |
164,21 → 136,19 |
if (argc == 1) |
getcwd(buff, PATH_MAX); |
else |
strncpy(buff, argv[1], PATH_MAX); |
str_cpy(buff, PATH_MAX, argv[1]); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_BOGUS: |
if (stat(buff, &s)) { |
cli_error(CL_ENOENT, buff); |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff); |
break; |
case LS_DIR: |
} |
if (s.is_file) { |
ls_print(buff, buff); |
} else { |
dirp = opendir(buff); |
if (! dirp) { |
if (!dirp) { |
/* May have been deleted between scoping it and opening it */ |
cli_error(CL_EFAIL, "Could not stat %s", buff); |
free(buff); |
186,7 → 156,6 |
} |
ls_scan_dir(buff, dirp); |
closedir(dirp); |
break; |
} |
free(buff); |
/branches/arm/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
9,8 → 9,7 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *); |
static void ls_print(const char *, const char *); |
#endif /* LS_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/ls/ls_def.h |
---|
3,14 → 3,4 |
"List files and directories", |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
{ |
"dir", |
NULL, |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/bdd/bdd.c |
---|
0,0 → 1,154 |
/* |
* Copyright (c) 2009 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 <string.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "bdd.h" |
#include "cmds.h" |
#include <libblock.h> |
#include <devmap.h> |
#include <errno.h> |
#define BLOCK_SIZE 512 |
#define BPR 16 |
static const char *cmdname = "bdd"; |
/* Dispays help for bdd in various levels */ |
void help_cmd_bdd(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s <device> [<block_number> [<bytes>]]\n"; |
if (level == HELP_SHORT) { |
printf("'%s' dump block device contents.\n", cmdname); |
} else { |
help_cmd_bdd(HELP_SHORT); |
printf(helpfmt, cmdname); |
} |
return; |
} |
/* Main entry point for bdd, accepts an array of arguments */ |
int cmd_bdd(char **argv) |
{ |
unsigned int argc; |
unsigned int i, j; |
dev_handle_t handle; |
block_t *block; |
uint8_t *blk; |
size_t size, bytes, rows; |
int rc; |
bn_t boff; |
uint8_t b; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
if (argc < 2 || argc > 4) { |
printf("%s - incorrect number of arguments.\n", cmdname); |
return CMD_FAILURE; |
} |
if (argc >= 3) |
boff = strtol(argv[2], NULL, 0); |
else |
boff = 0; |
if (argc >= 4) |
size = strtol(argv[3], NULL, 0); |
else |
size = 256; |
rc = devmap_device_get_handle(argv[1], &handle, 0); |
if (rc != EOK) { |
printf("Error: could not resolve device `%s'.\n", argv[1]); |
return CMD_FAILURE; |
} |
rc = block_init(handle, BLOCK_SIZE); |
if (rc != EOK) { |
printf("Error: could not init libblock.\n"); |
return CMD_FAILURE; |
} |
rc = block_cache_init(handle, BLOCK_SIZE, 2, CACHE_MODE_WB); |
if (rc != EOK) { |
printf("Error: could not init block cache.\n"); |
return CMD_FAILURE; |
} |
while (size > 0) { |
block = block_get(handle, boff, 0); |
blk = (uint8_t *) block->data; |
bytes = (size < BLOCK_SIZE) ? size : BLOCK_SIZE; |
rows = (bytes + BPR - 1) / BPR; |
for (j = 0; j < rows; j++) { |
for (i = 0; i < BPR; i++) { |
if (j * BPR + i < bytes) |
printf("%02x ", blk[j * BPR + i]); |
else |
printf(" "); |
} |
putchar('\t'); |
for (i = 0; i < BPR; i++) { |
if (j * BPR + i < bytes) { |
b = blk[j * BPR + i]; |
if (b >= 32 && b < 127) |
putchar(b); |
else |
putchar(' '); |
} else { |
putchar(' '); |
} |
} |
putchar('\n'); |
} |
block_put(block); |
if (size > rows * BPR) |
size -= rows * BPR; |
else |
size = 0; |
boff += rows * BPR; |
} |
block_fini(handle); |
return CMD_SUCCESS; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/bdd/bdd.h |
---|
0,0 → 1,8 |
#ifndef BDD_H |
#define BDD_H |
/* Prototypes for the bdd command, excluding entry points */ |
#endif /* BDD_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/bdd/entry.h |
---|
0,0 → 1,9 |
#ifndef BDD_ENTRY_H |
#define BDD_ENTRY_H |
/* Entry points for the bdd command */ |
extern int cmd_bdd(char **); |
extern void help_cmd_bdd(unsigned int); |
#endif /* BDD_ENTRY_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/bdd/bdd_def.h |
---|
0,0 → 1,7 |
{ |
"bdd", |
"Dump block device contents", |
&cmd_bdd, |
&help_cmd_bdd, |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/kcon/kcon.c |
---|
0,0 → 1,73 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 <io/console.h> |
#include <vfs/vfs.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "kcon.h" |
#include "cmds.h" |
static char *cmdname = "kcon"; |
/* Dispays help for kcon in various levels */ |
void help_cmd_kcon(unsigned int level) |
{ |
printf("`kcon' switches to the kernel debug console.\n"); |
if (level != HELP_SHORT) { |
printf("Usage: %s\n", cmdname); |
} |
return; |
} |
/* Main entry point for kcon, accepts an array of arguments */ |
int cmd_kcon(char **argv) |
{ |
unsigned int argc; |
argc = cli_count_args(argv); |
if (argc != 1) { |
printf("%s - incorrect number of arguments. Try `%s --help'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
console_kcon_enable(fphone(stdout)); |
return CMD_SUCCESS; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/kcon/kcon.h |
---|
0,0 → 1,8 |
#ifndef KCON_H |
#define KCON_H |
/* Prototypes for the kcon command, excluding entry points */ |
#endif /* KCON_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/kcon/entry.h |
---|
0,0 → 1,9 |
#ifndef KCON_ENTRY_H |
#define KCON_ENTRY_H |
/* Entry points for the kcon command */ |
extern int cmd_kcon(char **); |
extern void help_cmd_kcon(unsigned int); |
#endif /* KCON_ENTRY_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/kcon/kcon_def.h |
---|
0,0 → 1,7 |
{ |
"kcon", |
"Switch to kernel console", |
&cmd_kcon, |
&help_cmd_kcon, |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/pwd/pwd.c |
---|
30,6 → 30,7 |
#include <stdio.h> |
#include <stdlib.h> |
#include <mem.h> |
#include "config.h" |
#include "errors.h" |
/branches/arm/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h |
---|
3,5 → 3,4 |
"Prints the current working directory", |
&cmd_pwd, |
&help_cmd_pwd, |
-1 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c |
---|
37,6 → 37,7 |
#include <sys/stat.h> |
#include <getopt.h> |
#include <stdarg.h> |
#include <string.h> |
#include "config.h" |
#include "errors.h" |
93,7 → 94,7 |
/* Its a good idea to allocate path, plus we (may) need a copy of |
* path to tokenize if parents are specified */ |
if (NULL == (tmp = cli_strdup(path))) { |
if (NULL == (tmp = str_dup(path))) { |
cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
return 1; |
} |
128,9 → 129,9 |
absolute = 1; |
/* TODO: Canonify the path prior to tokenizing it, see below */ |
dirs[i] = cli_strtok(tmp, "/"); |
dirs[i] = strtok(tmp, "/"); |
while (dirs[i] && i < 255) |
dirs[++i] = cli_strtok(NULL, "/"); |
dirs[++i] = strtok(NULL, "/"); |
if (NULL == dirs[0]) |
return 1; |
149,7 → 150,7 |
while (dirs[i] != NULL) { |
/* Sometimes make or scripts conjoin odd paths. Account for something |
* like this: ../../foo/bar/../foo/foofoo/./bar */ |
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) { |
if (!str_cmp(dirs[i], "..") || !str_cmp(dirs[i], ".")) { |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: impossible path: %s", |
cmdname, path); |
/branches/arm/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h |
---|
3,14 → 3,6 |
"Create new directories", |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
{ |
"md", |
NULL, |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
33,8 → 33,9 |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <assert.h> |
#include <getopt.h> |
#include <mem.h> |
#include <string.h> |
#include "config.h" |
#include "errors.h" |
217,9 → 218,13 |
i = optind; |
while (NULL != argv[i]) { |
len = strlen(argv[i]) + 2; |
len = str_size(argv[i]) + 2; |
buff = (char *) realloc(buff, len); |
assert(buff != NULL); |
if (buff == NULL) { |
printf("rm: out of memory\n"); |
ret = 1; |
break; |
} |
memset(buff, 0, sizeof(buff)); |
snprintf(buff, len, argv[i]); |
/branches/arm/uspace/app/bdsh/cmds/modules/rm/rm_def.h |
---|
3,14 → 3,5 |
"Remove files and directories", |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
{ |
"del", |
NULL, |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/modules.h |
---|
18,9 → 18,9 |
/* Prototypes for each module's entry (help/exec) points */ |
#include "help/entry.h" |
#include "quit/entry.h" |
#include "mkdir/entry.h" |
#include "rm/entry.h" |
#include "bdd/entry.h" |
#include "cat/entry.h" |
#include "touch/entry.h" |
#include "ls/entry.h" |
27,6 → 27,9 |
#include "pwd/entry.h" |
#include "sleep/entry.h" |
#include "cp/entry.h" |
#include "mv/entry.h" |
#include "mount/entry.h" |
#include "kcon/entry.h" |
/* Each .def function fills the module_t struct with the individual name, entry |
* point, help entry point, etc. You can use config.h to control what modules |
34,9 → 37,9 |
module_t modules[] = { |
#include "help/help_def.h" |
#include "quit/quit_def.h" |
#include "mkdir/mkdir_def.h" |
#include "rm/rm_def.h" |
#include "bdd/bdd_def.h" |
#include "cat/cat_def.h" |
#include "touch/touch_def.h" |
#include "ls/ls_def.h" |
43,6 → 46,10 |
#include "pwd/pwd_def.h" |
#include "sleep/sleep_def.h" |
#include "cp/cp_def.h" |
#include "mv/mv_def.h" |
#include "mount/mount_def.h" |
#include "kcon/kcon_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
/branches/arm/uspace/app/bdsh/cmds/modules/mount/mount.c |
---|
0,0 → 1,82 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <vfs/vfs.h> |
#include <errno.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "mount.h" |
#include "cmds.h" |
static const char *cmdname = "mount"; |
/* Dispays help for mount in various levels */ |
void help_cmd_mount(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s <fstype> <mp> <dev> [<moptions>]\n"; |
if (level == HELP_SHORT) { |
printf("'%s' mounts a file system.\n", cmdname); |
} else { |
help_cmd_mount(HELP_SHORT); |
printf(helpfmt, cmdname); |
} |
return; |
} |
/* Main entry point for mount, accepts an array of arguments */ |
int cmd_mount(char **argv) |
{ |
unsigned int argc; |
char *mopts = ""; |
int rc; |
argc = cli_count_args(argv); |
if ((argc < 4) || (argc > 5)) { |
printf("%s: invalid number of arguments.\n", |
cmdname); |
return CMD_FAILURE; |
} |
if (argc == 5) |
mopts = argv[4]; |
rc = mount(argv[1], argv[2], argv[3], mopts, 0); |
if (rc != EOK) { |
printf("Unable to mount %s filesystem to %s on %s (rc=%d)\n", |
argv[1], argv[2], argv[3], rc); |
return CMD_FAILURE; |
} |
return CMD_SUCCESS; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/mount/mount_def.h |
---|
0,0 → 1,7 |
{ |
"mount", |
"The mount command", |
&cmd_mount, |
&help_cmd_mount, |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/mount/entry.h |
---|
0,0 → 1,9 |
#ifndef MOUNT_ENTRY_H |
#define MOUNT_ENTRY_H |
/* Entry points for the mount command */ |
extern int cmd_mount(char **); |
extern void help_cmd_mount(unsigned int); |
#endif /* MOUNT_ENTRY_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/mount/mount.h |
---|
0,0 → 1,8 |
#ifndef MOUNT_H |
#define MOUNT_H |
/* Prototypes for the mount command, excluding entry points */ |
#endif /* MOUNT_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/mv/mv.c |
---|
0,0 → 1,70 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <errno.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "mv.h" |
#include "cmds.h" |
static const char *cmdname = "mv"; |
/* Dispays help for mv in various levels */ |
void help_cmd_mv(unsigned int level) |
{ |
printf("'%s' renames files\n", cmdname); |
return; |
} |
/* Main entry point for mv, accepts an array of arguments */ |
int cmd_mv(char **argv) |
{ |
unsigned int argc; |
int rc; |
argc = cli_count_args(argv); |
if (argc != 3) { |
printf("%s: invalid number of arguments.\n", |
cmdname); |
return CMD_FAILURE; |
} |
rc = rename(argv[1], argv[2]); |
if (rc != EOK) { |
printf("Unable to rename %s to %s (rc=%d)\n", |
argv[1], argv[2], rc); |
return CMD_FAILURE; |
} |
return CMD_SUCCESS; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/mv/mv_def.h |
---|
0,0 → 1,14 |
{ |
"mv", |
"The mv command", |
&cmd_mv, |
&help_cmd_mv, |
}, |
{ |
"ren", |
NULL, |
&cmd_mv, |
&help_cmd_mv, |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/mv/entry.h |
---|
0,0 → 1,9 |
#ifndef MV_ENTRY_H |
#define MV_ENTRY_H |
/* Entry points for the mv command */ |
extern int cmd_mv(char **); |
extern void help_cmd_mv(unsigned int); |
#endif /* MV_ENTRY_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/mv/mv.h |
---|
0,0 → 1,8 |
#ifndef MV_H |
#define MV_H |
/* Prototypes for the mv command, excluding entry points */ |
#endif /* MV_H */ |
/branches/arm/uspace/app/bdsh/cmds/modules/module_aliases.h |
---|
12,10 → 12,7 |
* the entry point being reached. */ |
char *mod_aliases[] = { |
"exit", "quit", |
"md", "mkdir", |
"del", "rm", |
"dir", "ls", |
"ren", "mv", |
NULL, NULL |
}; |
/branches/arm/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
87,7 → 87,8 |
off_t total = 0; |
char *buff = NULL; |
if (-1 == (fd = open(fname, O_RDONLY))) { |
fd = open(fname, O_RDONLY); |
if (fd < 0) { |
printf("Unable to open %s\n", fname); |
return 1; |
} |
103,13 → 104,11 |
} |
do { |
memset(buff, 0, sizeof(buff)); |
bytes = read(fd, buff, blen); |
if (bytes > 0) { |
count += bytes; |
if (bytes < blen) |
buff[bytes] = '\0'; |
printf(buff); |
buff[bytes] = '\0'; |
printf("%s", buff); |
reads++; |
} |
} while (bytes > 0); |
/branches/arm/uspace/app/bdsh/cmds/modules/cat/cat_def.h |
---|
3,6 → 3,5 |
"Show the contents of a file", |
&cmd_cat, |
&help_cmd_cat, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/touch/touch.c |
---|
37,6 → 37,7 |
#include <fcntl.h> |
#include <dirent.h> |
#include <sys/types.h> |
#include <string.h> |
#include "config.h" |
#include "errors.h" |
79,7 → 80,7 |
} |
for (i = 1; i < argc; i ++) { |
buff = cli_strdup(argv[i]); |
buff = str_dup(argv[i]); |
dirp = opendir(buff); |
if (dirp) { |
cli_error(CL_ENOTSUP, "%s is a directory", buff); |
/branches/arm/uspace/app/bdsh/cmds/modules/touch/touch_def.h |
---|
3,6 → 3,5 |
"Create files or update access times", |
&cmd_touch, |
&help_cmd_touch, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/help/help.c |
---|
107,7 → 107,7 |
} |
if (argc == 3) { |
if (!strcmp("extended", argv[2])) |
if (!str_cmp("extended", argv[2])) |
level = HELP_LONG; |
else |
level = HELP_SHORT; |
133,13 → 133,11 |
/* First, show a list of built in commands that are available in this mode */ |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!builtin_is_restricted(i)) { |
if (is_builtin_alias(cmd->name)) |
printf(" %-16s\tAlias for `%s'\n", cmd->name, |
alias_for_builtin(cmd->name)); |
else |
printf(" %-16s\t%s\n", cmd->name, cmd->desc); |
} |
} |
i = 0; |
146,13 → 144,11 |
/* Now, show a list of module commands that are available in this mode */ |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!module_is_restricted(i)) { |
if (is_module_alias(mod->name)) |
printf(" %-16s\tAlias for `%s'\n", mod->name, |
alias_for_module(mod->name)); |
else |
printf(" %-16s\t%s\n", mod->name, mod->desc); |
} |
} |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
/branches/arm/uspace/app/bdsh/cmds/modules/help/help_def.h |
---|
3,5 → 3,4 |
"Show help for commands", |
&cmd_help, |
&help_cmd_help, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/cp/cp.c |
---|
30,6 → 30,10 |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <getopt.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
37,37 → 41,191 |
#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); |
/* TODO: re-insert assert() once this is stand alone, |
* removed as abort() exits the entire shell |
*/ |
if (res != 0) { |
printf("\n%d more bytes than actually exist were copied\n", res); |
goto err; |
} |
} |
if (bytes < 0) { |
err: |
printf("\nError copying %s, (%d)\n", src, bytes); |
copied = bytes; |
} |
out: |
close(fd1); |
close(fd2); |
if (buff) |
free(buff); |
return copied; |
} |
void help_cmd_cp(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
static char helpfmt[] = |
"Usage: %s [options] <source> <dest>\n" |
"Options: (* indicates not yet implemented)\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
"* -V, --verbose Be annoyingly noisy about what's being done\n" |
"* -f, --force Do not complain when <dest> exists\n" |
"* -r, --recursive Copy entire directories\n" |
" -b, --buffer ## Set the read buffer size to ##\n" |
"Currently, %s is under development, some options may not work.\n"; |
if (level == HELP_SHORT) { |
printf("`%s' copies files and directories\n", cmdname); |
} else { |
help_cmd_cp(HELP_SHORT); |
printf(helpfmt, cmdname, cmdname); |
} |
return; |
} |
/* Main entry point for cp, accepts an array of arguments */ |
int cmd_cp(char **argv) |
{ |
unsigned int argc; |
unsigned int i; |
unsigned int argc, buffer = 0, verbose = 0; |
int c, opt_ind; |
int64_t ret; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
argc = cli_count_args(argv); |
printf("%s %s\n", TEST_ANNOUNCE, cmdname); |
printf("%d arguments passed to %s", argc - 1, cmdname); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_cp(1); |
return CMD_SUCCESS; |
case 'v': |
printf("%d\n", CP_VERSION); |
return CMD_SUCCESS; |
case 'V': |
verbose = 1; |
break; |
case 'f': |
break; |
case 'r': |
break; |
case 'b': |
if (-1 == (buffer = strtoint(optarg))) { |
printf("%s: Invalid buffer specification, " |
"(should be a number greater than zero)\n", |
cmdname); |
return CMD_FAILURE; |
} |
if (verbose) |
printf("Buffer = %d\n", buffer); |
break; |
} |
} |
if (argc < 2) { |
printf("\n"); |
return CMD_SUCCESS; |
if (buffer == 0) |
buffer = CP_DEFAULT_BUFLEN; |
argc -= optind; |
if (argc != 2) { |
printf("%s: invalid number of arguments. Try %s --help\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose); |
return CMD_SUCCESS; |
if (verbose) |
printf("%d bytes copied\n", ret); |
if (ret >= 0) |
return CMD_SUCCESS; |
else |
return CMD_FAILURE; |
} |
/branches/arm/uspace/app/bdsh/cmds/modules/cp/cp_def.h |
---|
3,6 → 3,5 |
"Copy files and directories", |
&cmd_cp, |
&help_cmd_cp, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h |
---|
3,6 → 3,5 |
"Pause for given time interval (in seconds)", |
&cmd_sleep, |
&help_cmd_sleep, |
0 |
}, |
/branches/arm/uspace/app/bdsh/cmds/mod_cmds.c |
---|
53,26 → 53,6 |
extern volatile unsigned int cli_interactive; |
int module_is_restricted(int pos) |
{ |
/* Restriction Levels: |
* -1 -> Available only in interactive mode |
* 0 -> Available in any mode |
* 1 -> Available only in non-interactive mode */ |
module_t *mod = modules; |
mod += pos; |
/* We're interactive, and the module is OK to run */ |
if (cli_interactive && mod->restricted <= 0) |
return 0; |
/* We're not interactive, and the module is OK to run */ |
if (!cli_interactive && mod->restricted >= 0) |
return 0; |
/* Anything else is just a big fat no :) */ |
return 1; |
} |
/* Checks if an entry function matching command exists in modules[], if so |
* its position in the array is returned */ |
int is_module(const char *command) |
84,7 → 64,7 |
return -2; |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!strcmp(mod->name, command)) |
if (!str_cmp(mod->name, command)) |
return i; |
} |
101,7 → 81,7 |
return -1; |
for(i=0; mod_aliases[i] != NULL; i+=2) { |
if (!strcmp(mod_aliases[i], command)) |
if (!str_cmp(mod_aliases[i], command)) |
return 1; |
} |
117,7 → 97,7 |
return (char *)NULL; |
for(i=0; mod_aliases[i] != NULL; i++) { |
if (!strcmp(mod_aliases[i], command)) |
if (!str_cmp(mod_aliases[i], command)) |
return (char *)mod_aliases[++i]; |
i++; |
} |
/branches/arm/uspace/app/bdsh/cmds/builtin_cmds.c |
---|
40,19 → 40,6 |
extern volatile unsigned int cli_interactive; |
int builtin_is_restricted(int pos) |
{ |
builtin_t *cmd = builtins; |
cmd += pos; |
if (cli_interactive && cmd->restricted <= 0) |
return 0; |
if (!cli_interactive && cmd->restricted >= 0) |
return 0; |
return 1; |
} |
int is_builtin(const char *command) |
{ |
builtin_t *cmd; |
62,7 → 49,7 |
return -2; |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!strcmp(cmd->name, command)) |
if (!str_cmp(cmd->name, command)) |
return i; |
} |
77,7 → 64,7 |
return -1; |
for(i=0; builtin_aliases[i] != NULL; i+=2) { |
if (!strcmp(builtin_aliases[i], command)) |
if (!str_cmp(builtin_aliases[i], command)) |
return 1; |
} |
92,7 → 79,7 |
return (char *)NULL; |
for(i=0; builtin_aliases[i] != NULL; i++) { |
if (!strcmp(builtin_aliases[i], command)) |
if (!str_cmp(builtin_aliases[i], command)) |
return (char *)builtin_aliases[++i]; |
i++; |
} |
/branches/arm/uspace/app/bdsh/cmds/builtins/builtins.h |
---|
4,9 → 4,11 |
#include "config.h" |
#include "cd/entry.h" |
#include "exit/entry.h" |
builtin_t builtins[] = { |
#include "cd/cd_def.h" |
#include "exit/exit_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
/branches/arm/uspace/app/bdsh/cmds/builtins/exit/exit.h |
---|
0,0 → 1,6 |
#ifndef EXIT_H |
#define EXIT_H |
/* Prototypes for the quit command (excluding entry points) */ |
#endif |
/branches/arm/uspace/app/bdsh/cmds/builtins/exit/entry.h |
---|
0,0 → 1,12 |
#ifndef EXIT_ENTRY_H_ |
#define EXIT_ENTRY_H_ |
#include "scli.h" |
/* Entry points for the quit command */ |
extern void help_cmd_exit(unsigned int); |
extern int cmd_exit(char *[], cliuser_t *); |
#endif |
/branches/arm/uspace/app/bdsh/cmds/builtins/exit/exit.c |
---|
0,0 → 1,55 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 "entry.h" |
#include "exit.h" |
#include "cmds.h" |
static const char *cmdname = "exit"; |
extern volatile unsigned int cli_quit; |
extern const char *progname; |
void help_cmd_exit(unsigned int level) |
{ |
printf("Type `%s' to exit %s\n", cmdname, progname); |
return; |
} |
/* Quits the program and returns the status of whatever command |
* came before invoking 'quit' */ |
int cmd_exit(char *argv[], cliuser_t *usr) |
{ |
/* Inform that we're outta here */ |
cli_quit = 1; |
return CMD_SUCCESS; |
} |
/branches/arm/uspace/app/bdsh/cmds/builtins/exit/exit_def.h |
---|
0,0 → 1,6 |
{ |
"exit", |
"Exit the shell", |
&cmd_exit, |
&help_cmd_exit, |
}, |
/branches/arm/uspace/app/bdsh/cmds/builtins/cd/cd_def.h |
---|
3,12 → 3,4 |
"Change the current working directory", |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
{ |
"chdir", |
NULL, |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
/branches/arm/uspace/app/bdsh/cmds/builtins/builtin_aliases.h |
---|
4,7 → 4,6 |
/* See modules/module_aliases.h for an explanation of this file */ |
char *builtin_aliases[] = { |
"chdir", "cd", |
NULL, NULL |
}; |
/branches/arm/uspace/app/bdsh/cmds/mknewcmd |
---|
46,8 → 46,6 |
-e, --entry Entry function of the command (def: cmd_${def}) |
-h, --help-entry Entry function for command help (def: help_cmd_${def}) |
-a, --alias Alias (nickname) for this command (def: none) |
-r, --restrict Restriction level (interactive, non-interactive, both) |
(def: module is both, builtin is interactive only) |
-t, --type Type of command (module or builtin) (def: module) |
-H, --help This help summary |
-V, --version Print $PROGNAME version and exit normally |
67,8 → 65,7 |
$PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo |
The example would generate a modular command named 'foo', which is also |
reached by typing 'bar' and available in either interactive or noninteractive |
mode. |
reached by typing 'bar'. |
Skeletal files do *not* depend on the autoconf generated "config.h" unless you |
include it. This may or may not be desirable depending on your use. |
97,7 → 94,6 |
"${CMDDESC}", |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
107,7 → 103,6 |
NULL, |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
167,7 → 162,7 |
#include "${CMDNAME}.h" |
#include "cmds.h" |
static char *cmdname = "${CMDNAME}"; |
static const char *cmdname = "${CMDNAME}"; |
/* Dispays help for ${CMDNAME} in various levels */ |
void ${HELPENTRY}(unsigned int level) |
234,8 → 229,8 |
# We need at least one |
[ $# = 0 ] && usage && exit 1; |
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \ |
TEMP=$(getopt -o n:d:e:h:a:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,type:,help,version \ |
-- "$@") || { |
echo "Try $PROGNAME --help for help" |
} |
269,11 → 264,6 |
shift 2 |
continue |
;; |
-r | --restrict) |
CMDRESTRICT="$2" |
shift 2 |
continue |
;; |
-t | --type) |
CMDTYPE="$2" |
shift 2 |
305,30 → 295,7 |
[ -n "$CMDTYPE" ] || CMDTYPE="module" |
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}" |
# Builtins typically only need to be available in interactive mode, |
# set the default accordingly. |
[ -n "$CMDRESTRICT" ] || { |
[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both" |
[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive" |
} |
# Set the restriction level as the structure expects to see it |
case "$CMDRESTRICT" in |
0 | both) |
CMDRESTRICT="0" |
;; |
1 | non-interactive) |
CMDRESTRICT="1" |
;; |
-1 | interactive) |
CMDRESTRICT="-1" |
;; |
*) |
usage |
exit 1 |
;; |
esac |
# Do a little sanity |
[ -d $OUTDIR ] && { |
echo "$OUTDIR already exists, remove it to proceed." |
/branches/arm/uspace/app/bdsh/cmds/cmds.h |
---|
36,7 → 36,6 |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
int restricted; /* Restricts to interactive/non-interactive only */ |
} module_t; |
/* Builtin structure, same as modules except different types of entry points */ |
/branches/arm/uspace/app/bdsh/input.c |
---|
32,7 → 32,12 |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <io/stream.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <io/style.h> |
#include <vfs/vfs.h> |
#include <errno.h> |
#include <bool.h> |
#include "config.h" |
#include "util.h" |
41,21 → 46,8 |
#include "errors.h" |
#include "exec.h" |
extern volatile unsigned int cli_interactive; |
/* Not exposed in input.h */ |
static void cli_restricted(char *); |
static void read_line(char *, int); |
/* More than a macro than anything */ |
static void cli_restricted(char *cmd) |
{ |
printf("%s is not available in %s mode\n", cmd, |
cli_interactive ? "interactive" : "non-interactive"); |
return; |
} |
/* Tokenizes input from console, sees if the first word is a built-in, if so |
* invokes the built-in entry point (a[0]) passing all arguments in a[] to |
* the handler */ |
69,14 → 61,11 |
if (NULL == usr->line) |
return CL_EFAIL; |
tmp = cli_strdup(usr->line); |
tmp = str_dup(usr->line); |
/* Break up what the user typed, space delimited */ |
/* TODO: Protect things in quotes / ticks, expand wildcards */ |
cmd[n] = cli_strtok(tmp, " "); |
cmd[n] = strtok(tmp, " "); |
while (cmd[n] && n < WORD_MAX) { |
cmd[++n] = cli_strtok(NULL, " "); |
cmd[++n] = strtok(NULL, " "); |
} |
/* We have rubbish */ |
85,39 → 74,19 |
goto finit; |
} |
/* Its a builtin command */ |
/* Its a builtin command ? */ |
if ((i = (is_builtin(cmd[0]))) > -1) { |
/* Its not available in this mode, see what try_exec() thinks */ |
if (builtin_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
/* No external matching it could be found, tell the |
* user that the command does exist, but is not |
* available in this mode. */ |
cli_restricted(cmd[0]); |
goto finit; |
} |
/* Its a builtin, its available, run it */ |
rc = run_builtin(i, cmd, usr); |
goto finit; |
/* We repeat the same dance for modules */ |
/* Its a module ? */ |
} else if ((i = (is_module(cmd[0]))) > -1) { |
if (module_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
cli_restricted(cmd[0]); |
goto finit; |
} |
rc = run_module(i, cmd); |
goto finit; |
} else { |
/* Its not a module or builtin, restricted or otherwise. |
* See what try_exec() thinks of it and just pass its return |
* value back to the caller */ |
rc = try_exec(cmd[0], cmd); |
goto finit; |
} |
/* See what try_exec thinks of it */ |
rc = try_exec(cmd[0], cmd); |
finit: |
if (NULL != usr->line) { |
free(usr->line); |
129,31 → 98,46 |
return rc; |
} |
/* Borrowed from Jiri Svoboda's 'cli' uspace app */ |
static void read_line(char *buffer, int n) |
{ |
char c; |
int chars; |
console_event_t ev; |
size_t offs, otmp; |
wchar_t dec; |
chars = 0; |
while (chars < n - 1) { |
c = getchar(); |
if (c < 0) |
offs = 0; |
while (true) { |
fflush(stdout); |
if (!console_get_event(fphone(stdin), &ev)) |
return; |
if (c == '\n') |
if (ev.type != KEY_PRESS) |
continue; |
if (ev.key == KC_ENTER || ev.key == KC_NENTER) |
break; |
if (c == '\b') { |
if (chars > 0) { |
if (ev.key == KC_BACKSPACE) { |
if (offs > 0) { |
/* |
* Back up until we reach valid start of |
* character. |
*/ |
while (offs > 0) { |
--offs; otmp = offs; |
dec = str_decode(buffer, &otmp, n); |
if (dec != U_SPECIAL) |
break; |
} |
putchar('\b'); |
--chars; |
} |
continue; |
} |
putchar(c); |
buffer[chars++] = c; |
if (ev.c >= ' ') { |
if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK) |
putchar(ev.c); |
} |
} |
putchar('\n'); |
buffer[chars] = '\0'; |
buffer[offs] = '\0'; |
} |
/* TODO: |
162,15 → 146,18 |
void get_input(cliuser_t *usr) |
{ |
char line[INPUT_MAX]; |
size_t len = 0; |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
read_line(line, INPUT_MAX); |
len = strlen(line); |
/* Make sure we don't have rubbish or a C/R happy user */ |
if (len == 0 || line[0] == '\n') |
if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0) |
return; |
usr->line = cli_strdup(line); |
usr->line = str_dup(line); |
return; |
} |
/branches/arm/uspace/app/bdsh/Makefile |
---|
30,25 → 30,18 |
# POSSIBILITY OF SUCH DAMAGE. |
include ../../../version |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
LIBBLOCK_PREFIX = ../../lib/libblock |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
CFLAGS += -I../../srv/kbd/include -I$(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=$(RELEASE) |
ifdef REVISION |
DEFS += "-DREVISION=\"$(TIMESTAMP)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
PROGRAM = bdsh |
# Any directory that cleaning targets should know about |
57,9 → 50,9 |
cmds/ \ |
cmds/modules/ \ |
cmds/modules/help/ \ |
cmds/modules/quit/ \ |
cmds/modules/mkdir/ \ |
cmds/modules/rm/ \ |
cmds/modules/bdd/ \ |
cmds/modules/cat/ \ |
cmds/modules/touch/ \ |
cmds/modules/ls/ \ |
66,14 → 59,18 |
cmds/modules/pwd/ \ |
cmds/modules/sleep/ \ |
cmds/modules/cp/ \ |
cmds/modules/mv/ \ |
cmds/modules/mount/ \ |
cmds/modules/kcon/ \ |
cmds/builtins/ \ |
cmds/builtins/exit/\ |
cmds/builtins/cd/ |
SOURCES = \ |
cmds/modules/help/help.c \ |
cmds/modules/quit/quit.c \ |
cmds/modules/mkdir/mkdir.c \ |
cmds/modules/rm/rm.c \ |
cmds/modules/bdd/bdd.c \ |
cmds/modules/cat/cat.c \ |
cmds/modules/touch/touch.c \ |
cmds/modules/ls/ls.c \ |
80,6 → 77,10 |
cmds/modules/pwd/pwd.c \ |
cmds/modules/sleep/sleep.c \ |
cmds/modules/cp/cp.c \ |
cmds/modules/mv/mv.c \ |
cmds/modules/mount/mount.c \ |
cmds/modules/kcon/kcon.c \ |
cmds/builtins/exit/exit.c \ |
cmds/builtins/cd/cd.c \ |
cmds/mod_cmds.c \ |
cmds/builtin_cmds.c \ |
112,7 → 113,7 |
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d |
$(PROGRAM): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
# Everything else is a phony target |
.PHONY: all clean distclean depend disasm |
/branches/arm/uspace/app/bdsh/AUTHORS |
---|
8,9 → 8,6 |
* Based on the HelenOS testing sub-system written by Martin Decky |
* cli_strtok() and cli_strtok_r() (util.c) were adapted from the FreeBSD |
strtok() and strtok_r() functions written by Wes Peters. |
* read_line() (input.c) was written by Jiri Svoboda |
Individual author copyrights are listed in the headers of each file. |
/branches/arm/uspace/app/bdsh/util.c |
---|
1,7 → 1,4 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com> |
* Copyright (c) 1988, 1993 The Regents of the University of California. |
* All rights reserved by all copyright holders. |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> - All rights reserved |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
30,18 → 27,6 |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* NOTES: |
* 1 - Various functions were adapted from FreeBSD (copyright holders noted above) |
* these functions are identified with comments. |
* |
* 2 - Some of these have since appeared in libc. They remain here for various |
* reasons, such as the eventual integration of garbage collection for things |
* that allocate memory and don't automatically free it. |
* |
* 3 - Things that expect a pointer to an allocated string do _no_ sanity checking |
* if developing on a simulator with no debugger, take care :) |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdarg.h> |
54,190 → 39,6 |
extern volatile int cli_errno; |
/* some platforms do not have strdup, implement it here. |
* Returns a pointer to an allocated string or NULL on failure */ |
char * cli_strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) { |
cli_errno = CL_ENOMEM; |
return (char *) NULL; |
} |
cli_errno = CL_EOK; |
return (char *) memcpy(ret, s1, len); |
} |
/* |
* Take a previously allocated string (s1), re-size it to accept s2 and copy |
* the contents of s2 into s1. |
* Return -1 on failure, or the length of the copied string on success. |
*/ |
int cli_redup(char **s1, const char *s2) |
{ |
size_t len = strlen(s2) + 1; |
if (! len) |
return -1; |
*s1 = realloc(*s1, len); |
if (*s1 == NULL) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, s2, len); |
cli_errno = CL_EOK; |
return (int) len; |
} |
/* An asprintf() for formatting paths, similar to asprintf() but ensures |
* the returned allocated string is <= PATH_MAX. On failure, an attempt |
* is made to return the original string (if not null) unmodified. |
* |
* Returns: Length of the new string on success, 0 if the string was handed |
* back unmodified, -1 on failure. On failure, cli_errno is set. |
* |
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the |
* PATH_MAX defined by the kernel. |
* |
* Use this like: |
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) { |
* cli_error(cli_errno, "Failed to format path"); |
* stop_what_your_doing_as_your_out_of_memory(); |
* } |
*/ |
int cli_psprintf(char **s1, const char *fmt, ...) |
{ |
va_list ap; |
size_t needed, base = PATH_MAX + 1; |
int skipped = 0; |
char *orig = NULL; |
char *tmp = (char *) malloc(base); |
/* Don't even touch s1, not enough memory */ |
if (NULL == tmp) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* If re-allocating s1, save a copy in case we fail */ |
if (NULL != *s1) |
orig = cli_strdup(*s1); |
/* Print the string to tmp so we can determine the size that |
* we actually need */ |
memset(tmp, 0, sizeof(tmp)); |
va_start(ap, fmt); |
/* vsnprintf will return the # of bytes not written */ |
skipped = vsnprintf(tmp, base, fmt, ap); |
va_end(ap); |
/* realloc/alloc s1 to be just the size that we need */ |
needed = strlen(tmp) + 1; |
*s1 = realloc(*s1, needed); |
if (NULL == *s1) { |
/* No string lived here previously, or we failed to |
* make a copy of it, either way there's nothing we |
* can do. */ |
if (NULL == *orig) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* We can't even allocate enough size to restore the |
* saved copy, just give up */ |
*s1 = realloc(*s1, strlen(orig) + 1); |
if (NULL == *s1) { |
free(tmp); |
free(orig); |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* Give the string back as we found it */ |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, orig, strlen(orig) + 1); |
free(tmp); |
free(orig); |
cli_errno = CL_ENOMEM; |
return 0; |
} |
/* Ok, great, we have enough room */ |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, tmp, needed); |
free(tmp); |
/* Free tmp only if s1 was reallocated instead of allocated */ |
if (NULL != orig) |
free(orig); |
if (skipped) { |
/* s1 was bigger than PATH_MAX when expanded, however part |
* of the string was printed. Tell the caller not to use it */ |
cli_errno = CL_ETOOBIG; |
return -1; |
} |
/* Success! */ |
cli_errno = CL_EOK; |
return (int) needed; |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * cli_strtok_r(char *s, const char *delim, char **last) |
{ |
char *spanp, *tok; |
int c, sc; |
if (s == NULL && (s = *last) == NULL) { |
cli_errno = CL_EFAIL; |
return (NULL); |
} |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) |
goto cont; |
} |
if (c == 0) { /* no non-delimiter characters */ |
*last = NULL; |
return (NULL); |
} |
tok = s - 1; |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = '\0'; |
*last = s; |
return (tok); |
} |
} while (sc != 0); |
} |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * cli_strtok(char *s, const char *delim) |
{ |
static char *last; |
return (cli_strtok_r(s, delim, &last)); |
} |
/* Count and return the # of elements in an array */ |
unsigned int cli_count_args(char **args) |
{ |
273,10 → 74,7 |
if (NULL == usr->cwd) |
snprintf(usr->cwd, PATH_MAX, "(unknown)"); |
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) { |
cli_error(cli_errno, "Failed to set prompt"); |
return 1; |
} |
asprintf(&usr->prompt, "%s # ", usr->cwd); |
return 0; |
} |
/branches/arm/uspace/app/bdsh/util.h |
---|
3,13 → 3,6 |
#include "scli.h" |
/* Internal string handlers */ |
extern char * cli_strdup(const char *); |
extern int cli_redup(char **, const char *); |
extern int cli_psprintf(char **, const char *, ...); |
extern char * cli_strtok_r(char *, const char *, char **); |
extern char * cli_strtok(char *, const char *); |
/* Utility functions */ |
extern unsigned int cli_count_args(char **); |
extern unsigned int cli_set_prompt(cliuser_t *usr); |
/branches/arm/uspace/app/bdsh/scli.c |
---|
45,7 → 45,6 |
/* Globals that are modified during start-up that modules/builtins |
* should be aware of. */ |
volatile unsigned int cli_quit = 0; |
volatile unsigned int cli_interactive = 1; |
volatile unsigned int cli_verbocity = 1; |
/* The official name of this program |
/branches/arm/uspace/app/getvc/getvc.c |
---|
0,0 → 1,109 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup getvc GetVC |
* @brief Console initialization task. |
* @{ |
*/ |
/** |
* @file |
*/ |
#include <sys/types.h> |
#include <unistd.h> |
#include <stdio.h> |
#include <task.h> |
#include "version.h" |
static void usage(void) |
{ |
printf("Usage: getvc <device> <path>\n"); |
} |
static void closeall(void) |
{ |
fclose(stdin); |
fclose(stdout); |
fclose(stderr); |
close(0); |
close(1); |
close(2); |
} |
static task_id_t spawn(char *fname) |
{ |
char *argv[2]; |
argv[0] = fname; |
argv[1] = NULL; |
task_id_t id = task_spawn(fname, argv); |
if (id == 0) |
printf("Error spawning %s\n", fname); |
return id; |
} |
int main(int argc, char *argv[]) |
{ |
task_exit_t texit; |
int retval; |
if (argc < 3) { |
usage(); |
return -1; |
} |
closeall(); |
stdin = fopen(argv[1], "r"); |
stdout = fopen(argv[1], "w"); |
stderr = fopen(argv[1], "w"); |
/* |
* FIXME: fopen() should actually detect that we are opening a console |
* and it should set line-buffering mode automatically. |
*/ |
setvbuf(stdout, NULL, _IOLBF, BUFSIZ); |
if ((stdin == NULL) |
|| (stdout == NULL) |
|| (stderr == NULL)) |
return -2; |
version_print(argv[1]); |
task_id_t id = spawn(argv[2]); |
task_wait(id, &texit, &retval); |
return 0; |
} |
/** @} |
*/ |
/branches/arm/uspace/app/getvc/version.c |
---|
0,0 → 1,67 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup getvc |
* @{ |
*/ |
/** |
* @file |
*/ |
#include <unistd.h> |
#include <stdio.h> |
#include <macros.h> |
#include "getvc.h" |
#include "version.h" |
static char *release = STRING(RELEASE); |
static char *name = STRING(NAME); |
static char *arch = STRING(UARCH); |
#ifdef REVISION |
static char *revision = ", revision " STRING(REVISION); |
#else |
static char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
static char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
static char *timestamp = ""; |
#endif |
/** Print version information. */ |
void version_print(const char *vc) |
{ |
printf("HelenOS release %s (%s)%s%s\n", release, name, revision, timestamp); |
printf("Running on %s (%s)\n", arch, vc); |
printf("Copyright (c) 2001-2009 HelenOS project\n\n"); |
} |
/** @} |
*/ |
/branches/arm/uspace/app/getvc/version.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup getvc |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef VERSION_H__ |
#define VERSION_H__ |
extern void version_print(const char *vc); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/app/getvc/Makefile |
---|
0,0 → 1,79 |
# |
# Copyright (c) 2009 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
include ../../../version |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=$(RELEASE) "-DNAME=$(NAME)" |
## Sources |
# |
OUTPUT = getvc |
SOURCES = \ |
getvc.c \ |
version.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/app/getvc/getvc.h |
---|
0,0 → 1,42 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup getvc |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef GETVC_H__ |
#define GETVC_H__ |
#endif |
/** @} |
*/ |
/branches/arm/uspace/app/tester/devmap/devmap1.c |
---|
File deleted |
/branches/arm/uspace/app/tester/devmap/devmap1.def |
---|
File deleted |
/branches/arm/uspace/app/tester/console/console1.c |
---|
0,0 → 1,123 |
/* |
* 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 <io/console.h> |
#include <io/color.h> |
#include <io/style.h> |
#include <vfs/vfs.h> |
#include <async.h> |
#include "../tester.h" |
const char *color_name[] = { |
[COLOR_BLACK] = "black", |
[COLOR_BLUE] = "blue", |
[COLOR_GREEN] = "green", |
[COLOR_CYAN] = "cyan", |
[COLOR_RED] = "red", |
[COLOR_MAGENTA] = "magenta", |
[COLOR_YELLOW] = "yellow", |
[COLOR_WHITE] = "white" |
}; |
char *test_console1(void) |
{ |
if (!test_quiet) { |
printf("Style test: "); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
printf("normal "); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
printf("emphasized"); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
printf(".\n"); |
unsigned int i; |
unsigned int j; |
printf("\nForeground color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
fflush(stdout); |
console_set_color(fphone(stdout), i, COLOR_WHITE, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
printf("\nBackground color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_WHITE, i, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
printf("\nRGB colors test:\n"); |
for (i = 0; i < 255; i += 16) { |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 16); |
putchar('X'); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8); |
putchar('X'); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xffffff, i); |
putchar('X'); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
return NULL; |
} |
/branches/arm/uspace/app/tester/console/console1.def |
---|
0,0 → 1,6 |
{ |
"console1", |
"Console color test", |
&test_console1, |
true |
}, |
/branches/arm/uspace/app/tester/stdio/stdio1.c |
---|
0,0 → 1,90 |
/* |
* 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 <errno.h> |
#include "../tester.h" |
#define BUF_SIZE 32 |
static char buf[BUF_SIZE + 1]; |
char *test_stdio1(void) |
{ |
FILE *file; |
char *file_name = "/readme"; |
TPRINTF("Open file \"%s\"...", file_name); |
errno = 0; |
file = fopen(file_name, "rt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
TPRINTF("Read file..."); |
size_t cnt = fread(buf, 1, BUF_SIZE, file); |
if (ferror(file)) { |
TPRINTF("errno = %d\n", errno); |
fclose(file); |
return "Failed reading file"; |
} else |
TPRINTF("OK\n"); |
buf[cnt] = '\0'; |
TPRINTF("Read %u bytes, string \"%s\"\n", cnt, buf); |
TPRINTF("Seek to beginning..."); |
if (fseek(file, 0, SEEK_SET) != 0) { |
TPRINTF("errno = %d\n", errno); |
fclose(file); |
return "Failed seeking in file"; |
} else |
TPRINTF("OK\n"); |
TPRINTF("Read using fgetc()..."); |
while (true) { |
int c = fgetc(file); |
if (c == EOF) |
break; |
TPRINTF("."); |
} |
TPRINTF("[EOF]\n"); |
TPRINTF("Close..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
return NULL; |
} |
/branches/arm/uspace/app/tester/stdio/stdio2.c |
---|
0,0 → 1,83 |
/* |
* 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 <errno.h> |
#include "../tester.h" |
char *test_stdio2(void) |
{ |
FILE *file; |
char *file_name = "/test"; |
TPRINTF("Open file \"%s\" for writing...", file_name); |
errno = 0; |
file = fopen(file_name, "wt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
TPRINTF("Write to file..."); |
fprintf(file, "integer: %u, string: \"%s\"", 42, "Hello!"); |
TPRINTF("OK\n"); |
TPRINTF("Close..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
TPRINTF("Open file \"%s\" for reading...", file_name); |
file = fopen(file_name, "rt"); |
if (file == NULL) { |
TPRINTF("errno = %d\n", errno); |
return "Failed opening file"; |
} else |
TPRINTF("OK\n"); |
TPRINTF("File contains:\n"); |
while (true) { |
int c = fgetc(file); |
if (c == EOF) |
break; |
TPRINTF("%c", c); |
} |
TPRINTF("\nClose..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
return NULL; |
} |
/branches/arm/uspace/app/tester/stdio/stdio1.def |
---|
0,0 → 1,6 |
{ |
"stdio1", |
"ANSI C streams reading test", |
&test_stdio1, |
true |
}, |
/branches/arm/uspace/app/tester/stdio/stdio2.def |
---|
0,0 → 1,6 |
{ |
"stdio2", |
"ANSI C streams writing test", |
&test_stdio2, |
true |
}, |
/branches/arm/uspace/app/tester/tester.c |
---|
27,10 → 27,10 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup tester User space Tester |
* @brief User space testing infrastructure. |
/** @addtogroup tester User space tester |
* @brief User space testing infrastructure. |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
37,42 → 37,44 |
#include <unistd.h> |
#include <stdio.h> |
#include <string.h> |
#include "tester.h" |
int myservice = 0; |
int phones[MAX_PHONES]; |
int connections[MAX_CONNECTIONS]; |
ipc_callid_t callids[MAX_CONNECTIONS]; |
bool test_quiet; |
int test_argc; |
char **test_argv; |
test_t tests[] = { |
#include "thread/thread1.def" |
#include "print/print1.def" |
#include "print/print2.def" |
#include "print/print3.def" |
#include "print/print4.def" |
#include "console/console1.def" |
#include "stdio/stdio1.def" |
#include "stdio/stdio2.def" |
#include "fault/fault1.def" |
#include "fault/fault2.def" |
#include "vfs/vfs1.def" |
#include "ipc/ping_pong.def" |
#include "ipc/register.def" |
#include "ipc/connect.def" |
#include "ipc/send_async.def" |
#include "ipc/send_sync.def" |
#include "ipc/answer.def" |
#include "ipc/hangup.def" |
#include "devmap/devmap1.def" |
#include "vfs/vfs1.def" |
{NULL, NULL, NULL} |
#include "loop/loop1.def" |
#include "mm/malloc1.def" |
{NULL, NULL, NULL, false} |
}; |
static bool run_test(test_t *test) |
{ |
printf("%s\t\t%s\n", test->name, test->desc); |
/* Execute the test */ |
char * ret = test->entry(false); |
char *ret = test->entry(); |
if (ret == NULL) { |
printf("Test passed\n\n"); |
printf("\nTest passed\n"); |
return true; |
} |
printf("%s\n\n", ret); |
printf("\n%s\n", ret); |
return false; |
} |
81,11 → 83,12 |
test_t *test; |
unsigned int i = 0; |
unsigned int n = 0; |
printf("\n*** Running all safe tests ***\n\n"); |
for (test = tests; test->name != NULL; test++) { |
if (test->safe) { |
printf("%s (%s)\n", test->name, test->desc); |
if (run_test(test)) |
i++; |
else |
92,61 → 95,52 |
n++; |
} |
} |
printf("\nSafe tests completed, %u tests run, %u passed.\n\n", i + n, i); |
printf("\nCompleted, %u tests run, %u passed.\n", i + n, i); |
} |
static void list_tests(void) |
{ |
size_t len = 0; |
test_t *test; |
char c = 'a'; |
for (test = tests; test->name != NULL; test++) { |
if (str_length(test->name) > len) |
len = str_length(test->name); |
} |
for (test = tests; test->name != NULL; test++, c++) |
printf("%c\t%s\t\t%s%s\n", c, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
for (test = tests; test->name != NULL; test++) |
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("*\t\t\tRun all safe tests\n"); |
printf("%-*s Run all safe tests\n", len, "*"); |
} |
int main(int argc, char **argv) |
int main(int argc, char *argv[]) |
{ |
printf("Number of arguments: %d\n", argc); |
if (argv) { |
printf("Arguments:"); |
while (*argv) { |
printf(" '%s'", *argv++); |
} |
printf("\n"); |
if (argc < 2) { |
printf("Usage:\n\n"); |
printf("%s <test> [args ...]\n\n", argv[0]); |
list_tests(); |
return 0; |
} |
while (1) { |
char c; |
test_t *test; |
list_tests(); |
printf("> "); |
c = getchar(); |
printf("%c\n", c); |
if ((c >= 'a') && (c <= 'z')) { |
for (test = tests; test->name != NULL; test++, c--) |
if (c == 'a') |
break; |
if (test->name == NULL) |
printf("Unknown test\n\n"); |
else |
run_test(test); |
} else if (c == '*') { |
run_safe_tests(); |
} else if (c < 0) { |
/* got EOF */ |
break; |
} else { |
printf("Invalid test\n\n"); |
test_quiet = false; |
test_argc = argc - 2; |
test_argv = argv + 2; |
if (str_cmp(argv[1], "*") == 0) { |
run_safe_tests(); |
return 0; |
} |
test_t *test; |
for (test = tests; test->name != NULL; test++) { |
if (str_cmp(argv[1], test->name) == 0) { |
return (run_test(test) ? 0 : -1); |
} |
} |
printf("Unknown test \"%s\"\n", argv[1]); |
return -2; |
} |
/** @} |
/branches/arm/uspace/app/tester/thread/thread1.c |
---|
27,7 → 27,8 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#define THREADS 5 |
#define THREADS 20 |
#define DELAY 10 |
#include <atomic.h> |
#include <thread.h> |
42,40 → 43,38 |
static void threadtest(void *data) |
{ |
thread_detach(thread_get_id()); |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", thread_get_id()); |
while (atomic_get(&finish)) |
usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
char * test_thread1(bool quiet) |
char *test_thread1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
unsigned int i; |
unsigned int total = 0; |
atomic_set(&finish, 1); |
atomic_set(&threads_finished, 0); |
for (i = 0; i < THREADS; i++) { |
TPRINTF("Creating threads"); |
for (i = 0; i < THREADS; i++) { |
if (thread_create(threadtest, NULL, "threadtest", NULL) < 0) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("\nCould not create thread %u\n", i); |
break; |
} |
TPRINTF("."); |
total++; |
} |
if (!quiet) |
printf("Running threads for 10 seconds...\n"); |
sleep(10); |
TPRINTF("\nRunning threads for %u seconds...", DELAY); |
sleep(DELAY); |
TPRINTF("\n"); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
TPRINTF("Threads left: %u\n", total - atomic_get(&threads_finished)); |
sleep(1); |
} |
/branches/arm/uspace/app/tester/loop/loop1.c |
---|
0,0 → 1,40 |
/* |
* 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(void) |
{ |
TPRINTF("Looping..."); |
while (true); |
TPRINTF("\n"); |
return "Survived endless loop"; |
} |
/branches/arm/uspace/app/tester/loop/loop1.def |
---|
0,0 → 1,6 |
{ |
"loop1", |
"Endless loop", |
&test_loop1, |
false |
}, |
/branches/arm/uspace/app/tester/fault/fault1.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault1(bool quiet) |
char *test_fault1(void) |
{ |
((int *)(0))[1] = 0; |
/branches/arm/uspace/app/tester/fault/fault2.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault2(bool quiet) |
char *test_fault2(void) |
{ |
volatile long long var; |
volatile int var1; |
/branches/arm/uspace/app/tester/ipc/send_sync.def |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/answer.def |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/send_async.def |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/answer.c |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/hangup.def |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/send_async.c |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/send_sync.c |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/hangup.c |
---|
File deleted |
/branches/arm/uspace/app/tester/ipc/ping_pong.c |
---|
0,0 → 1,78 |
/* |
* Copyright (c) 2009 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 <sys/time.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <errno.h> |
#include "../tester.h" |
#define DURATION_SECS 10 |
#define COUNT_GRANULARITY 100 |
char *test_ping_pong(void) |
{ |
TPRINTF("Pinging ns server for %d seconds...", DURATION_SECS); |
struct timeval start; |
if (gettimeofday(&start, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
uint64_t count = 0; |
while (true) { |
struct timeval now; |
if (gettimeofday(&now, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) |
break; |
size_t i; |
for (i = 0; i < COUNT_GRANULARITY; i++) { |
int retval = async_req_0_0(PHONE_NS, NS_PING); |
if (retval != EOK) { |
TPRINTF("\n"); |
return "Failed to send ping message"; |
} |
} |
count += COUNT_GRANULARITY; |
} |
TPRINTF("OK\nCompleted %llu round trips in %u seconds, %llu rt/s.\n", |
count, DURATION_SECS, count / DURATION_SECS); |
return NULL; |
} |
/branches/arm/uspace/app/tester/ipc/register.c |
---|
32,58 → 32,58 |
#include <errno.h> |
#include "../tester.h" |
#define MAX_CONNECTIONS 50 |
static int connections[MAX_CONNECTIONS]; |
static void client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phonehash = icall->in_phone_hash; |
int retval; |
int i; |
printf("Connected phone: %P, accepting\n", icall->in_phone_hash); |
unsigned int i; |
TPRINTF("Connected phone %#x accepting\n", icall->in_phone_hash); |
ipc_answer_0(iid, EOK); |
for (i = 0; i < 1024; i++) |
for (i = 0; i < MAX_CONNECTIONS; i++) { |
if (!connections[i]) { |
connections[i] = phonehash; |
connections[i] = icall->in_phone_hash; |
break; |
} |
} |
while (1) { |
callid = async_get_call(&call); |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
int retval; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("Phone (%P) hung up.\n", phonehash); |
TPRINTF("Phone %#x hung up\n", icall->in_phone_hash); |
retval = 0; |
break; |
case IPC_TEST_METHOD: |
TPRINTF("Received well known message from %#x: %#x\n", |
icall->in_phone_hash, callid); |
ipc_answer_0(callid, EOK); |
break; |
default: |
printf("Received message from %P: %X\n", phonehash, |
callid); |
for (i = 0; i < 1024; i++) |
if (!callids[i]) { |
callids[i] = callid; |
break; |
} |
continue; |
TPRINTF("Received unknown message from %#x: %#x\n", |
icall->in_phone_hash, callid); |
ipc_answer_0(callid, ENOENT); |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
char * test_register(bool quiet) |
char *test_register(void) |
{ |
int i; |
async_set_client_connection(client_connection); |
for (i = IPC_TEST_START; i < IPC_TEST_START + 10; i++) { |
ipcarg_t phonead; |
int res = ipc_connect_to_me(PHONE_NS, i, 0, 0, &phonead); |
if (!res) |
break; |
printf("Failed registering as %d..:%d\n", i, res); |
} |
printf("Registered as service: %d\n", i); |
myservice = i; |
ipcarg_t phonead; |
int res = ipc_connect_to_me(PHONE_NS, IPC_TEST_SERVICE, 0, 0, &phonead); |
if (res != 0) |
return "Failed registering IPC service"; |
TPRINTF("Registered as service %u, accepting connections\n", IPC_TEST_SERVICE); |
async_manager(); |
return NULL; |
} |
/branches/arm/uspace/app/tester/ipc/connect.c |
---|
28,32 → 28,46 |
#include <stdio.h> |
#include <unistd.h> |
#include <atomic.h> |
#include "../tester.h" |
char * test_connect(bool quiet) |
static atomic_t finish; |
static void callback(void *priv, int retval, ipc_call_t *data) |
{ |
char c; |
int svc; |
int phid; |
atomic_set(&finish, 1); |
} |
printf("Choose one service: 0:10000....9:10009 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '0' || c > '9'); |
char *test_connect(void) |
{ |
TPRINTF("Connecting to %u...", IPC_TEST_SERVICE); |
int phone = ipc_connect_me_to(PHONE_NS, IPC_TEST_SERVICE, 0, 0); |
if (phone > 0) { |
TPRINTF("phoneid %d\n", phone); |
} else { |
TPRINTF("\n"); |
return "ipc_connect_me_to() failed"; |
} |
svc = IPC_TEST_START + c - '0'; |
if (svc == myservice) |
return "Currently cannot connect to myself, update test"; |
printf("Sending synchronous message...\n"); |
int retval = ipc_call_sync_0_0(phone, IPC_TEST_METHOD); |
TPRINTF("Received response to synchronous message\n"); |
printf("Connecting to %d..", svc); |
phid = ipc_connect_me_to(PHONE_NS, svc, 0, 0); |
if (phid > 0) { |
printf("phoneid: %d\n", phid); |
phones[phid] = 1; |
} else |
return "Error"; |
TPRINTF("Sending asynchronous message...\n"); |
atomic_set(&finish, 0); |
ipc_call_async_0(phone, IPC_TEST_METHOD, NULL, callback, 1); |
while (atomic_get(&finish) != 1) |
TPRINTF("."); |
TPRINTF("Received response to asynchronous message\n"); |
TPRINTF("Hanging up..."); |
retval = ipc_hangup(phone); |
if (retval == 0) { |
TPRINTF("OK\n"); |
} else { |
TPRINTF("\n"); |
return "ipc_hangup() failed"; |
} |
return NULL; |
} |
/branches/arm/uspace/app/tester/ipc/ping_pong.def |
---|
0,0 → 1,6 |
{ |
"ping_pong", |
"IPC ping-pong benchmark", |
&test_ping_pong, |
true |
}, |
/branches/arm/uspace/app/tester/print/print2.c |
---|
0,0 → 1,52 |
/* |
* Copyright (c) 2005 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. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
char *test_print2(void) |
{ |
TPRINTF("Testing printf(\"%%c %%3.2c %%-3.2c %%2.3c %%-2.3c\", 'a', 'b', 'c', 'd', 'e'):\n"); |
TPRINTF("Expected output: [a] [ b] [c ] [ d] [e ]\n"); |
TPRINTF("Real output: [%c] [%3.2c] [%-3.2c] [%2.3c] [%-2.3c]\n\n", 'a', 'b', 'c', 'd', 'e'); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", 1, 2, 3, 4, 5):\n"); |
TPRINTF("Expected output: [1] [ 02] [03 ] [004] [005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", 1, 2, 3, 4, 5); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", -1, -2, -3, -4, -5):\n"); |
TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); |
TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); |
TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); |
TPRINTF("Real output: [%#x] [%#5.3x] [%#-5.3x] [%#3.5x] [%#-3.5x]\n\n", 17, 18, 19, 20, 21); |
return NULL; |
} |
/branches/arm/uspace/app/tester/print/print3.c |
---|
0,0 → 1,62 |
/* |
* Copyright (c) 2005 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. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <macros.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char *test_print3(void) |
{ |
char buffer[BUFFER_SIZE]; |
int retval; |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=30 buffer=\"Short text without parameters.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very very very long text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=44 buffer=\"Very very very long text withou\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short %%s.\", \"text\"):\n"); |
TPRINTF("Expected result: retval=11 buffer=\"Short text.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s.", "text"); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very long %%s. This text's length is more than %%d. We are interested in the result.\", \"text\", " STRING(BUFFER_SIZE) "):\n"); |
TPRINTF("Expected result: retval=84 buffer=\"Very long text. This text's len\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text's length is more than %d. We are interested in the result.", "text", BUFFER_SIZE); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
return NULL; |
} |
/branches/arm/uspace/app/tester/print/print4.c |
---|
0,0 → 1,83 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
char *test_print4(void) |
{ |
TPRINTF("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
uint8_t group; |
for (group = 1; group < 4; group++) { |
TPRINTF("%#x: ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%c", (char) ((group << 5) + index)); |
TPRINTF(" "); |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
TPRINTF("\n"); |
} |
TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
for (group = 4; group < 8; group++) { |
TPRINTF("%#x: ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
TPRINTF("\n"); |
} |
TPRINTF("\nUTF-8 strings using printf(\"%%s\"):\n"); |
TPRINTF("English: %s\n", "Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %s\n", "á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %s\n", "ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
TPRINTF("\nUTF-32 strings using printf(\"%%ls\"):\n"); |
TPRINTF("English: %ls\n", L"Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %ls\n", L"á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %ls\n", L"ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
return NULL; |
} |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/app/tester/print/print1.def |
---|
1,6 → 1,6 |
{ |
"print1", |
"Printf test", |
"String printf test", |
&test_print1, |
true |
}, |
/branches/arm/uspace/app/tester/print/print2.def |
---|
0,0 → 1,6 |
{ |
"print2", |
"Numeric printf test", |
&test_print2, |
true |
}, |
/branches/arm/uspace/app/tester/print/print3.def |
---|
0,0 → 1,6 |
{ |
"print3", |
"Buffered printf test", |
&test_print3, |
true |
}, |
/branches/arm/uspace/app/tester/print/print1.c |
---|
30,44 → 30,27 |
#include <unistd.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char * test_print1(bool quiet) |
char *test_print1(void) |
{ |
if (!quiet) { |
int retval; |
unsigned int nat = 0x12345678u; |
char buffer[BUFFER_SIZE]; |
printf(" text 10.8s %*.*s \n", 5, 3, "text"); |
printf(" very long text 10.8s %10.8s \n", "very long text"); |
printf(" text 8.10s %8.10s \n", "text"); |
printf(" very long text 8.10s %8.10s \n", "very long text"); |
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n",'a', 'b', 'c', 'd', 'e' ); |
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",1, 1, 1, 1, 1 ); |
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 ); |
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 ); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
printf(" Print to NULL '%s'\n", NULL); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print short text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s", "text"); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print long text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text`s length is more than %d. We are interested in the result.", "text" , BUFFER_SIZE); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
} |
TPRINTF("Testing printf(\"%%*.*s\", 5, 3, \"text\"):\n"); |
TPRINTF("Expected output: \" tex\"\n"); |
TPRINTF("Real output: \"%*.*s\"\n\n", 5, 3, "text"); |
TPRINTF("Testing printf(\"%%10.8s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \" very lon\"\n"); |
TPRINTF("Real output: \"%10.8s\"\n\n", "very long text"); |
TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n"); |
TPRINTF("Expected output: \"text\"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "text"); |
TPRINTF("Testing printf(\"%%8.10s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \"very long \"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "very long text"); |
TPRINTF("Testing printf(\"%%s\", NULL):\n"); |
TPRINTF("Expected output: \"(NULL)\"\n"); |
TPRINTF("Real output: \"%s\"\n\n", NULL); |
return NULL; |
} |
/branches/arm/uspace/app/tester/print/print4.def |
---|
0,0 → 1,6 |
{ |
"print4", |
"Unicode test", |
&test_print4, |
true |
}, |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/app/tester/tester.h |
---|
39,37 → 39,45 |
#include <bool.h> |
#include <ipc/ipc.h> |
#define IPC_TEST_START 10000 |
#define MAX_PHONES 20 |
#define MAX_CONNECTIONS 50 |
#define TEST_SKIPPED "Test Skipped" |
#define IPC_TEST_SERVICE 10240 |
#define IPC_TEST_METHOD 2000 |
extern int myservice; |
extern int phones[MAX_PHONES]; |
extern int connections[MAX_CONNECTIONS]; |
extern ipc_callid_t callids[MAX_CONNECTIONS]; |
extern bool test_quiet; |
extern int test_argc; |
extern char **test_argv; |
typedef char * (* test_entry_t)(bool); |
#define TPRINTF(format, ...) \ |
{ \ |
if (!test_quiet) { \ |
fprintf(stderr, format, ##__VA_ARGS__); \ |
} \ |
} |
typedef char *(*test_entry_t)(void); |
typedef struct { |
char * name; |
char * desc; |
char *name; |
char *desc; |
test_entry_t entry; |
bool safe; |
} test_t; |
extern char * test_thread1(bool quiet); |
extern char * test_print1(bool quiet); |
extern char * test_fault1(bool quiet); |
extern char * test_fault2(bool quiet); |
extern char * test_register(bool quiet); |
extern char * test_connect(bool quiet); |
extern char * test_send_async(bool quiet); |
extern char * test_send_sync(bool quiet); |
extern char * test_answer(bool quiet); |
extern char * test_hangup(bool quiet); |
extern char * test_devmap1(bool quiet); |
extern char * test_vfs1(bool quiet); |
extern char *test_thread1(void); |
extern char *test_print1(void); |
extern char *test_print2(void); |
extern char *test_print3(void); |
extern char *test_print4(void); |
extern char *test_console1(void); |
extern char *test_stdio1(void); |
extern char *test_stdio2(void); |
extern char *test_fault1(void); |
extern char *test_fault2(void); |
extern char *test_vfs1(void); |
extern char *test_ping_pong(void); |
extern char *test_register(void); |
extern char *test_connect(void); |
extern char *test_loop1(void); |
extern char *test_malloc1(void); |
extern test_t tests[]; |
/branches/arm/uspace/app/tester/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
44,16 → 45,20 |
SOURCES = tester.c \ |
thread/thread1.c \ |
print/print1.c \ |
print/print2.c \ |
print/print3.c \ |
print/print4.c \ |
console/console1.c \ |
stdio/stdio1.c \ |
stdio/stdio2.c \ |
fault/fault1.c \ |
fault/fault2.c \ |
vfs/vfs1.c \ |
ipc/ping_pong.c \ |
ipc/register.c \ |
ipc/connect.c \ |
ipc/send_async.c \ |
ipc/send_sync.c \ |
ipc/answer.c \ |
ipc/hangup.c \ |
devmap/devmap1.c \ |
vfs/vfs1.c |
loop/loop1.c \ |
mm/malloc1.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
64,18 → 69,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/app/tester/vfs/vfs1.c |
---|
34,109 → 34,118 |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include "../tester.h" |
char text[] = "O xein', angellein Lakedaimoniois hoti teide " |
"keimetha tois keinon rhemasi peithomenoi."; |
#define FS_TYPE "tmpfs" |
#define MOUNT_POINT "/tmp" |
#define OPTIONS "" |
#define FLAGS 0 |
char *test_vfs1(bool quiet) |
#define TEST_DIRECTORY MOUNT_POINT "/testdir" |
#define TEST_FILE TEST_DIRECTORY "/testfile" |
#define TEST_FILE2 TEST_DIRECTORY "/nextfile" |
#define MAX_DEVICE_NAME 32 |
#define BUF_SIZE 16 |
static char text[] = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; |
static char *read_root(void) |
{ |
int rc; |
TPRINTF("Opening the root directory..."); |
DIR *dirp = opendir("/"); |
if (!dirp) { |
TPRINTF("\n"); |
return "opendir() failed"; |
} else |
TPRINTF("OK\n"); |
struct dirent *dp; |
while ((dp = readdir(dirp))) |
TPRINTF(" node \"%s\"\n", dp->d_name); |
closedir(dirp); |
return NULL; |
} |
rc = mount("tmpfs", "/", "nulldev0"); |
char *test_vfs1(void) |
{ |
if (mkdir(MOUNT_POINT, 0) != 0) |
return "mkdir() failed"; |
TPRINTF("Created directory %s\n", MOUNT_POINT); |
char null[MAX_DEVICE_NAME]; |
int null_id = devmap_null_create(); |
if (null_id == -1) |
return "Unable to create null device"; |
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id); |
int rc = mount(FS_TYPE, MOUNT_POINT, null, OPTIONS, FLAGS); |
switch (rc) { |
case EOK: |
if (!quiet) |
printf("mounted tmpfs on /\n"); |
TPRINTF("Mounted /dev/%s as %s on %s\n", null, FS_TYPE, MOUNT_POINT); |
break; |
case EBUSY: |
if (!quiet) |
printf("(INFO) something is already mounted on /\n"); |
TPRINTF("(INFO) Filesystem already mounted on %s\n", MOUNT_POINT); |
break; |
default: |
if (!quiet) |
printf("(INFO) IPC returned errno %d\n", rc); |
return "mount() failed."; |
TPRINTF("(ERR) IPC returned errno %d (is tmpfs loaded?)\n", rc); |
return "mount() failed"; |
} |
if (mkdir("/mydir", 0) != 0) |
return "mkdir() failed.\n"; |
if (!quiet) |
printf("created directory /mydir\n"); |
int fd0 = open("/mydir/myfile", O_CREAT); |
if (mkdir(TEST_DIRECTORY, 0) != 0) |
return "mkdir() failed"; |
TPRINTF("Created directory %s\n", TEST_DIRECTORY); |
int fd0 = open(TEST_FILE, O_CREAT); |
if (fd0 < 0) |
return "open() failed.\n"; |
if (!quiet) |
printf("created file /mydir/myfile, fd=%d\n", fd0); |
ssize_t cnt; |
return "open() failed"; |
TPRINTF("Created file %s (fd=%d)\n", TEST_FILE, fd0); |
size_t size = sizeof(text); |
cnt = write(fd0, text, size); |
ssize_t cnt = write(fd0, text, size); |
if (cnt < 0) |
return "write() failed.\n"; |
if (!quiet) |
printf("written %d bytes, fd=%d\n", cnt, fd0); |
return "write() failed"; |
TPRINTF("Written %d bytes\n", cnt); |
if (lseek(fd0, 0, SEEK_SET) != 0) |
return "lseek() failed.\n"; |
if (!quiet) |
printf("sought to position 0, fd=%d\n", fd0); |
char buf[10]; |
while ((cnt = read(fd0, buf, sizeof(buf)))) { |
return "lseek() failed"; |
TPRINTF("Sought to position 0\n"); |
char buf[BUF_SIZE]; |
while ((cnt = read(fd0, buf, BUF_SIZE))) { |
if (cnt < 0) |
return "read() failed.\n"; |
if (!quiet) |
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt, |
buf, fd0); |
return "read() failed"; |
TPRINTF("Read %d bytes: \".*s\"\n", cnt, cnt, buf); |
} |
close(fd0); |
DIR *dirp; |
struct dirent *dp; |
if (!quiet) |
printf("scanning the root directory...\n"); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
if (rename("/mydir/myfile", "/mydir/yourfile")) |
return "rename() failed.\n"; |
if (!quiet) |
printf("renamed /mydir/myfile to /mydir/yourfile\n"); |
if (unlink("/mydir/yourfile")) |
return "unlink() failed.\n"; |
if (!quiet) |
printf("unlinked file /mydir/yourfile\n"); |
if (rmdir("/mydir")) |
return "rmdir() failed.\n"; |
if (!quiet) |
printf("removed directory /mydir\n"); |
char *rv = read_root(); |
if (rv != NULL) |
return rv; |
if (!quiet) |
printf("scanning the root directory...\n"); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
if (rename(TEST_FILE, TEST_FILE2)) |
return "rename() failed"; |
TPRINTF("Renamed %s to %s\n", TEST_FILE, TEST_FILE2); |
if (unlink(TEST_FILE2)) |
return "unlink() failed"; |
TPRINTF("Unlinked %s\n", TEST_FILE2); |
if (rmdir(TEST_DIRECTORY)) |
return "rmdir() failed"; |
TPRINTF("Removed directory %s\n", TEST_DIRECTORY); |
rv = read_root(); |
if (rv != NULL) |
return rv; |
return NULL; |
} |
/branches/arm/uspace/app/tester/mm/malloc1.def |
---|
0,0 → 1,6 |
{ |
"malloc1", |
"Memory allocator test", |
&test_malloc1, |
true |
}, |
/branches/arm/uspace/app/tester/mm/malloc1.c |
---|
0,0 → 1,651 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Tomas Bures |
* Copyright (c) 2009 Lubomir Bulej |
* 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 <unistd.h> |
#include <stdlib.h> |
#include <malloc.h> |
#include "../tester.h" |
/* |
* The test consists of several phases which differ in the size of blocks |
* they allocate. The size of blocks is given as a range of minimum and |
* maximum allowed size. Each of the phases is divided into 3 subphases which |
* differ in the probability of free and alloc actions. Second subphase is |
* started when malloc returns 'out of memory' or when MAX_ALLOC is reached. |
* Third subphase is started after a given number of cycles. The third subphase |
* as well as the whole phase ends when all memory blocks are released. |
*/ |
/** |
* sizeof_array |
* @array array to determine the size of |
* |
* Returns the size of @array in array elements. |
*/ |
#define sizeof_array(array) \ |
(sizeof(array) / sizeof((array)[0])) |
#define MAX_ALLOC (16 * 1024 * 1024) |
/* |
* Subphase control structures: subphase termination conditions, |
* probabilities of individual actions, subphase control structure. |
*/ |
typedef struct { |
unsigned int max_cycles; |
unsigned int no_memory; |
unsigned int no_allocated; |
} sp_term_cond_s; |
typedef struct { |
unsigned int alloc; |
unsigned int free; |
} sp_action_prob_s; |
typedef struct { |
char *name; |
sp_term_cond_s cond; |
sp_action_prob_s prob; |
} subphase_s; |
/* |
* Phase control structures: The minimum and maximum block size that |
* can be allocated during the phase execution, phase control structure. |
*/ |
typedef struct { |
size_t min_block_size; |
size_t max_block_size; |
} ph_alloc_size_s; |
typedef struct { |
char *name; |
ph_alloc_size_s alloc; |
subphase_s *subphases; |
} phase_s; |
/* |
* Subphases are defined separately here. This is for two reasons: |
* 1) data are not duplicated, 2) we don't have to state beforehand |
* how many subphases a phase contains. |
*/ |
static subphase_s subphases_32B[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 200, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_128K[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 70, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 30, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 30, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_default[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
/* |
* Phase definitions. |
*/ |
static phase_s phases[] = { |
{ |
.name = "32 B memory blocks", |
.alloc = { |
.min_block_size = 32, |
.max_block_size = 32 |
}, |
.subphases = subphases_32B |
}, |
{ |
.name = "128 KB memory blocks", |
.alloc = { |
.min_block_size = 128 * 1024, |
.max_block_size = 128 * 1024 |
}, |
.subphases = subphases_128K |
}, |
{ |
.name = "2500 B memory blocks", |
.alloc = { |
.min_block_size = 2500, |
.max_block_size = 2500 |
}, |
.subphases = subphases_default |
}, |
{ |
.name = "1 B .. 250000 B memory blocks", |
.alloc = { |
.min_block_size = 1, |
.max_block_size = 250000 |
}, |
.subphases = subphases_default |
} |
}; |
/* |
* Global error flag. The flag is set if an error |
* is encountered (overlapping blocks, inconsistent |
* block data, etc.) |
*/ |
static bool error_flag = false; |
/* |
* Memory accounting: the amount of allocated memory and the |
* number and list of allocated blocks. |
*/ |
static size_t mem_allocated; |
static size_t mem_blocks_count; |
static LIST_INITIALIZE(mem_blocks); |
typedef struct { |
/* Address of the start of the block */ |
void *addr; |
/* Size of the memory block */ |
size_t size; |
/* link to other blocks */ |
link_t link; |
} mem_block_s; |
typedef mem_block_s *mem_block_t; |
/** init_mem |
* |
* Initializes the memory accounting structures. |
* |
*/ |
static void init_mem(void) |
{ |
mem_allocated = 0; |
mem_blocks_count = 0; |
} |
static bool overlap_match(link_t *entry, void *addr, size_t size) |
{ |
mem_block_t mblk = list_get_instance(entry, mem_block_s, link); |
/* Entry block control structure <mbeg, mend) */ |
uint8_t *mbeg = (uint8_t *) mblk; |
uint8_t *mend = (uint8_t *) mblk + sizeof(mem_block_s); |
/* Entry block memory <bbeg, bend) */ |
uint8_t *bbeg = (uint8_t *) mblk->addr; |
uint8_t *bend = (uint8_t *) mblk->addr + mblk->size; |
/* Data block <dbeg, dend) */ |
uint8_t *dbeg = (uint8_t *) addr; |
uint8_t *dend = (uint8_t *) addr + size; |
/* Check for overlaps */ |
if (((mbeg >= dbeg) && (mbeg < dend)) || |
((mend > dbeg) && (mend <= dend)) || |
((bbeg >= dbeg) && (bbeg < dend)) || |
((bend > dbeg) && (bend <= dend))) |
return true; |
return false; |
} |
/** test_overlap |
* |
* Test whether a block starting at @addr overlaps with another, previously |
* allocated memory block or its control structure. |
* |
* @param addr Initial address of the block |
* @param size Size of the block |
* |
* @return false if the block does not overlap. |
* |
*/ |
static int test_overlap(void *addr, size_t size) |
{ |
link_t *entry; |
bool fnd = false; |
for (entry = mem_blocks.next; entry != &mem_blocks; entry = entry->next) { |
if (overlap_match(entry, addr, size)) { |
fnd = true; |
break; |
} |
} |
return fnd; |
} |
/** checked_malloc |
* |
* Allocate @size bytes of memory and check whether the chunk comes |
* from the non-mapped memory region and whether the chunk overlaps |
* with other, previously allocated, chunks. |
* |
* @param size Amount of memory to allocate |
* |
* @return NULL if the allocation failed. Sets the global error_flag to |
* true if the allocation succeeded but is illegal. |
* |
*/ |
static void *checked_malloc(size_t size) |
{ |
void *data; |
/* Allocate the chunk of memory */ |
data = malloc(size); |
if (data == NULL) |
return NULL; |
/* Check for overlaps with other chunks */ |
if (test_overlap(data, size)) { |
TPRINTF("\nError: Allocated block overlaps with another " |
"previously allocated block.\n"); |
error_flag = true; |
} |
return data; |
} |
/** alloc_block |
* |
* Allocate a block of memory of @size bytes and add record about it into |
* the mem_blocks list. Return a pointer to the block holder structure or |
* NULL if the allocation failed. |
* |
* If the allocation is illegal (e.g. the memory does not come from the |
* right region or some of the allocated blocks overlap with others), |
* set the global error_flag. |
* |
* @param size Size of the memory block |
* |
*/ |
static mem_block_t alloc_block(size_t size) |
{ |
/* Check for allocation limit */ |
if (mem_allocated >= MAX_ALLOC) |
return NULL; |
/* Allocate the block holder */ |
mem_block_t block = (mem_block_t) checked_malloc(sizeof(mem_block_s)); |
if (block == NULL) |
return NULL; |
link_initialize(&block->link); |
/* Allocate the block memory */ |
block->addr = checked_malloc(size); |
if (block->addr == NULL) { |
free(block); |
return NULL; |
} |
block->size = size; |
/* Register the allocated block */ |
list_append(&block->link, &mem_blocks); |
mem_allocated += size + sizeof(mem_block_s); |
mem_blocks_count++; |
return block; |
} |
/** free_block |
* |
* Free the block of memory and the block control structure allocated by |
* alloc_block. Set the global error_flag if an error occurs. |
* |
* @param block Block control structure |
* |
*/ |
static void free_block(mem_block_t block) |
{ |
/* Unregister the block */ |
list_remove(&block->link); |
mem_allocated -= block->size + sizeof(mem_block_s); |
mem_blocks_count--; |
/* Free the memory */ |
free(block->addr); |
free(block); |
} |
/** expected_value |
* |
* Compute the expected value of a byte located at @pos in memory |
* block described by @blk. |
* |
* @param blk Memory block control structure |
* @param pos Position in the memory block data area |
* |
*/ |
static inline uint8_t expected_value(mem_block_t blk, uint8_t *pos) |
{ |
return ((unsigned long) blk ^ (unsigned long) pos) & 0xff; |
} |
/** fill_block |
* |
* Fill the memory block controlled by @blk with data. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void fill_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) |
*pos = expected_value(blk, pos); |
} |
/** check_block |
* |
* Check whether the block @blk contains the data it was filled with. |
* Set global error_flag if an error occurs. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void check_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) { |
if (*pos != expected_value (blk, pos)) { |
TPRINTF("\nError: Corrupted content of a data block.\n"); |
error_flag = true; |
return; |
} |
} |
} |
static link_t *list_get_nth(link_t *list, unsigned int i) |
{ |
unsigned int cnt = 0; |
link_t *entry; |
for (entry = list->next; entry != list; entry = entry->next) { |
if (cnt == i) |
return entry; |
cnt++; |
} |
return NULL; |
} |
/** get_random_block |
* |
* Select a random memory block from the list of allocated blocks. |
* |
* @return Block control structure or NULL if the list is empty. |
* |
*/ |
static mem_block_t get_random_block(void) |
{ |
if (mem_blocks_count == 0) |
return NULL; |
unsigned int blkidx = rand() % mem_blocks_count; |
link_t *entry = list_get_nth(&mem_blocks, blkidx); |
if (entry == NULL) { |
TPRINTF("\nError: Corrupted list of allocated memory blocks.\n"); |
error_flag = true; |
} |
return list_get_instance(entry, mem_block_s, link); |
} |
#define RETURN_IF_ERROR \ |
{ \ |
if (error_flag) \ |
return; \ |
} |
static void do_subphase(phase_s *phase, subphase_s *subphase) |
{ |
unsigned int cycles; |
for (cycles = 0; /* always */; cycles++) { |
if (subphase->cond.max_cycles && |
cycles >= subphase->cond.max_cycles) { |
/* |
* We have performed the required number of |
* cycles. End the current subphase. |
*/ |
break; |
} |
/* |
* Decide whether we alloc or free memory in this step. |
*/ |
unsigned int rnd = rand() % 100; |
if (rnd < subphase->prob.alloc) { |
/* Compute a random number lying in interval <min_block_size, max_block_size> */ |
int alloc = phase->alloc.min_block_size + |
(rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1)); |
mem_block_t blk = alloc_block(alloc); |
RETURN_IF_ERROR; |
if (blk == NULL) { |
TPRINTF("F(A)"); |
if (subphase->cond.no_memory) { |
/* We filled the memory. Proceed to next subphase */ |
break; |
} |
} else { |
TPRINTF("A"); |
fill_block(blk); |
} |
} else if (rnd < subphase->prob.free) { |
mem_block_t blk = get_random_block(); |
if (blk == NULL) { |
TPRINTF("F(R)"); |
if (subphase->cond.no_allocated) { |
/* We free all the memory. Proceed to next subphase. */ |
break; |
} |
} else { |
TPRINTF("R"); |
check_block(blk); |
RETURN_IF_ERROR; |
free_block(blk); |
RETURN_IF_ERROR; |
} |
} |
} |
TPRINTF("\n.. finished.\n"); |
} |
static void do_phase(phase_s *phase) |
{ |
unsigned int subno; |
for (subno = 0; subno < 3; subno++) { |
subphase_s *subphase = & phase->subphases [subno]; |
TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name); |
do_subphase(phase, subphase); |
RETURN_IF_ERROR; |
} |
} |
char *test_malloc1(void) |
{ |
init_mem(); |
unsigned int phaseno; |
for (phaseno = 0; phaseno < sizeof_array(phases); phaseno++) { |
phase_s *phase = &phases[phaseno]; |
TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name); |
do_phase(phase); |
if (error_flag) |
break; |
TPRINTF("Phase finished.\n"); |
} |
if (error_flag) |
return "Test failed"; |
return NULL; |
} |
/branches/arm/uspace/app/trace/trace.c |
---|
35,7 → 35,6 |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <syscall.h> |
#include <ipc/ipc.h> |
#include <fibril.h> |
#include <errno.h> |
42,13 → 41,17 |
#include <udebug.h> |
#include <async.h> |
#include <task.h> |
#include <mem.h> |
#include <string.h> |
#include <loader/loader.h> |
#include <libc.h> |
// Temporary: service and method names |
#include "proto.h" |
#include <ipc/services.h> |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/console/console.h" |
#include <ipc/console.h> |
#include "syscalls.h" |
#include "ipcp.h" |
444,10 → 447,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); |
468,23 → 481,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; |
} |
} |
491,7 → 497,7 |
} |
printf("Finished tracing thread [%d]\n", thread_id); |
printf("Finished tracing thread [%d].\n", thread_id); |
return 0; |
} |
515,7 → 521,7 |
int rc; |
/* Spawn a program loader */ |
ldr = loader_spawn(); |
ldr = loader_connect(); |
if (ldr == NULL) |
return 0; |
579,6 → 585,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); |
585,6 → 592,7 |
} |
if (c == 'r') { |
paused = 0; |
printf("Resume...\n"); |
} |
} |
617,7 → 625,7 |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER |
V_INTEGER |
}; |
next_thread_id = 1; |
627,26 → 635,36 |
p = proto_new("vfs"); |
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_READ, o); |
proto_add_oper(p, VFS_IN_READ, o); |
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_WRITE, o); |
proto_add_oper(p, VFS_IN_WRITE, o); |
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_TRUNCATE, o); |
proto_add_oper(p, VFS_IN_TRUNCATE, o); |
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MOUNT, o); |
proto_add_oper(p, VFS_IN_MOUNT, o); |
/* o = oper_new("unmount", 0, arg_def); |
proto_add_oper(p, VFS_UNMOUNT, o);*/ |
proto_add_oper(p, VFS_IN_UNMOUNT, o);*/ |
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_OPEN, o); |
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_CLOSE, o); |
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_SEEK, o); |
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_MKDIR, o); |
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_UNLINK, o); |
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_IN_RENAME, o); |
proto_register(SERVICE_VFS, p); |
p = proto_new("console"); |
resp_def[0] = V_CHAR; |
o = oper_new("getchar", 0, arg_def, V_INTEGER, 2, resp_def); |
proto_add_oper(p, CONSOLE_GETCHAR, o); |
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER; |
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR; |
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def); |
arg_def[0] = V_CHAR; |
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_PUTCHAR, o); |
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CLEAR, o); |
656,13 → 674,17 |
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER; |
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def); |
proto_add_oper(p, CONSOLE_GETSIZE, o); |
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_FLUSH, o); |
proto_add_oper(p, CONSOLE_GET_SIZE, o); |
arg_def[0] = V_INTEGER; |
o = oper_new("set_style", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_STYLE, o); |
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER; arg_def[2] = V_INTEGER; |
o = oper_new("set_color", 3, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_COLOR, o); |
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER; |
o = oper_new("set_style", 2, arg_def, V_INTEGER, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_STYLE, o); |
o = oper_new("set_rgb_color", 2, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_RGB_COLOR, o); |
o = oper_new("cursor_visibility", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CURSOR_VISIBILITY, o); |
701,7 → 723,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); |
} |
776,6 → 798,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; |
786,11 → 809,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/arm/uspace/app/trace/proto.c |
---|
35,7 → 35,7 |
#include <stdio.h> |
#include <stdlib.h> |
#include <ipc/ipc.h> |
#include <libadt/hash_table.h> |
#include <adt/hash_table.h> |
#include "trace.h" |
#include "proto.h" |
/branches/arm/uspace/app/trace/proto.h |
---|
35,7 → 35,7 |
#ifndef PROTO_H_ |
#define PROTO_H_ |
#include <libadt/hash_table.h> |
#include <adt/hash_table.h> |
#include <ipc/ipc.h> |
#include "trace.h" |
/branches/arm/uspace/app/trace/ipcp.c |
---|
34,7 → 34,7 |
#include <stdio.h> |
#include <stdlib.h> |
#include <libadt/hash_table.h> |
#include <adt/hash_table.h> |
#include "ipc_desc.h" |
#include "proto.h" |
/branches/arm/uspace/app/trace/syscalls.c |
---|
59,11 → 59,14 |
[SYS_IPC_ANSWER_FAST] = { "ipc_answer_fast", 6, V_ERRNO }, |
[SYS_IPC_ANSWER_SLOW] = { "ipc_answer_slow", 2, V_ERRNO }, |
[SYS_IPC_FORWARD_FAST] = { "ipc_forward_fast", 6, V_ERRNO }, |
[SYS_IPC_FORWARD_SLOW] = { "ipc_forward_slow", 3, V_ERRNO }, |
[SYS_IPC_WAIT] = { "ipc_wait_for_call", 3, V_HASH }, |
[SYS_IPC_HANGUP] = { "ipc_hangup", 1, V_ERRNO }, |
[SYS_IPC_REGISTER_IRQ] = { "ipc_register_irq", 4, V_ERRNO }, |
[SYS_IPC_UNREGISTER_IRQ] = { "ipc_unregister_irq", 2, V_ERRNO }, |
[SYS_EVENT_SUBSCRIBE] = { "event_subscribe", 2, V_ERRNO }, |
[SYS_CAP_GRANT] = { "cap_grant", 2, V_ERRNO }, |
[SYS_CAP_REVOKE] = { "cap_revoke", 2, V_ERRNO }, |
[SYS_PHYSMEM_MAP] = { "physmem_map", 4, V_ERRNO }, |
/branches/arm/uspace/app/trace/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
63,7 → 64,7 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
/branches/arm/uspace/app/klog/klog.c |
---|
27,9 → 27,9 |
*/ |
/** @addtogroup klog KLog |
* @brief HelenOS KLog |
* @brief HelenOS KLog |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
40,56 → 40,47 |
#include <ipc/services.h> |
#include <as.h> |
#include <sysinfo.h> |
#include <io/stream.h> |
#include <event.h> |
#include <errno.h> |
#include <io/klog.h> |
#define NAME "klog" |
#define NAME "klog" |
#define KLOG_SIZE PAGE_SIZE |
/* Pointer to klog area */ |
static char *klog; |
static wchar_t *klog; |
static size_t klog_length; |
static void console_wait(void) |
{ |
while (get_cons_phone() < 0) |
usleep(50000); // FIXME |
} |
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
async_serialize_start(); |
size_t klog_start = (size_t) IPC_GET_ARG1(*call); |
size_t klog_len = (size_t) IPC_GET_ARG2(*call); |
size_t klog_stored = (size_t) IPC_GET_ARG3(*call); |
size_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
putchar(klog[(klog_start + i) % KLOG_SIZE]); |
async_serialize_end(); |
putchar(klog[(klog_start + i) % klog_length]); |
} |
int main(int argc, char *argv[]) |
{ |
console_wait(); |
size_t klog_pages = sysinfo_value("klog.pages"); |
size_t klog_size = klog_pages * PAGE_SIZE; |
klog_length = klog_size / sizeof(wchar_t); |
klog = (char *) as_get_mappable_page(KLOG_SIZE); |
klog = (wchar_t *) as_get_mappable_page(klog_size); |
if (klog == NULL) { |
printf(NAME ": Error allocating memory area\n"); |
return -1; |
} |
int res = ipc_share_in_start_1_0(PHONE_NS, (void *) klog, KLOG_SIZE, |
SERVICE_MEM_KLOG); |
int res = ipc_share_in_start_1_0(PHONE_NS, (void *) klog, |
klog_size, SERVICE_MEM_KLOG); |
if (res != EOK) { |
printf(NAME ": Error initializing memory area\n"); |
return -1; |
} |
int inr = sysinfo_value("klog.inr"); |
int devno = sysinfo_value("klog.devno"); |
if (ipc_register_irq(inr, devno, 0, NULL) != EOK) { |
if (event_subscribe(EVENT_KLOG, 0) != EOK) { |
printf(NAME ": Error registering klog notifications\n"); |
return -1; |
} |
97,7 → 88,7 |
async_set_interrupt_received(interrupt_received); |
klog_update(); |
async_manager(); |
return 0; |
} |
/branches/arm/uspace/app/klog/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
52,18 → 53,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/lib/libc/malloc/malloc.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/libadt/fifo.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/libadt/hash_table.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/libadt/list.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/io/io.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/io/stream.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/include/io/console.h |
---|
0,0 → 1,86 |
/* |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IO_CONSOLE_H_ |
#define LIBC_IO_CONSOLE_H_ |
#include <ipc/ipc.h> |
#include <bool.h> |
typedef enum { |
KEY_PRESS, |
KEY_RELEASE |
} console_ev_type_t; |
enum { |
CONSOLE_CCAP_NONE = 0, |
CONSOLE_CCAP_STYLE, |
CONSOLE_CCAP_INDEXED, |
CONSOLE_CCAP_RGB |
}; |
/** Console event structure. */ |
typedef struct { |
/** Press or release event. */ |
console_ev_type_t type; |
/** Keycode of the key that was pressed or released. */ |
unsigned int key; |
/** Bitmask of modifiers held. */ |
unsigned int mods; |
/** The character that was generated or '\0' for none. */ |
wchar_t c; |
} console_event_t; |
extern void console_clear(int phone); |
extern int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols); |
extern void console_goto(int phone, ipcarg_t row, ipcarg_t col); |
extern void console_set_style(int phone, int style); |
extern void console_set_color(int phone, int fg_color, int bg_color, int flags); |
extern void console_set_rgb_color(int phone, int fg_color, int bg_color); |
extern void console_cursor_visibility(int phone, bool show); |
extern int console_get_color_cap(int phone, int *ccap); |
extern void console_kcon_enable(int phone); |
extern bool console_get_event(int phone, console_event_t *event); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/io/printf_core.h |
---|
39,19 → 39,20 |
#include <stdarg.h> |
/** Structure for specifying output methods for different printf clones. */ |
struct printf_spec { |
/* Output function, returns count of printed characters or EOF */ |
int (*write)(void *, size_t, void *); |
/* Support data - output stream specification, its state, locks,... */ |
typedef struct printf_spec { |
/* String output function, returns number of printed characters or EOF */ |
int (*str_write)(const char *, size_t, void *); |
/* Wide string output function, returns number of printed characters or EOF */ |
int (*wstr_write)(const wchar_t *, size_t, void *); |
/* User data - output stream specification, state, locks, etc. */ |
void *data; |
} printf_spec_t; |
}; |
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap); |
int printf_core(const char *fmt, struct printf_spec *ps ,va_list ap); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/io/klog.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2006 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_STREAM_H_ |
#define LIBC_STREAM_H_ |
#include <sys/types.h> |
extern size_t klog_write(const void *buf, size_t size); |
extern void klog_update(void); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/io/color.h |
---|
0,0 → 1,55 |
/* |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IO_COLOR_H_ |
#define LIBC_IO_COLOR_H_ |
enum console_color { |
COLOR_BLACK = 0, |
COLOR_BLUE = 1, |
COLOR_GREEN = 2, |
COLOR_CYAN = 3, |
COLOR_RED = 4, |
COLOR_MAGENTA = 5, |
COLOR_YELLOW = 6, |
COLOR_WHITE = 7, |
CATTR_BRIGHT = 8, |
CATTR_BLINK = 8 |
}; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/io/style.h |
---|
0,0 → 1,46 |
/* |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IO_STYLE_H_ |
#define LIBC_IO_STYLE_H_ |
enum console_style { |
STYLE_NORMAL = 0, |
STYLE_EMPHASIS = 1 |
}; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/io/keycode.h |
---|
0,0 → 1,220 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IO_KEYCODE_H_ |
#define LIBC_IO_KEYCODE_H_ |
/** Keycode definitions. |
* |
* A keycode identifies a key by its position on the keyboard, rather |
* than by its label. For human readability, key positions are noted |
* with the key label on a keyboard with US layout. This label has |
* nothing to do with the character, that the key produces |
* -- this is determined by the keymap. |
* |
* The keyboard model reflects a standard PC keyboard layout. |
* Non-standard keyboards need to be mapped to this model in some |
* logical way. Scancodes are mapped to keycodes with a scanmap. |
* |
* For easier mapping to the model and to emphasize the nature of keycodes, |
* they really are organized here by position, rather than by label. |
*/ |
enum keycode { |
/* Main block row 1 */ |
KC_BACKTICK = 1, |
KC_1, |
KC_2, |
KC_3, |
KC_4, |
KC_5, |
KC_6, |
KC_7, |
KC_8, |
KC_9, |
KC_0, |
KC_MINUS, |
KC_EQUALS, |
KC_BACKSPACE, |
/* Main block row 2 */ |
KC_TAB, |
KC_Q, |
KC_W, |
KC_E, |
KC_R, |
KC_T, |
KC_Y, |
KC_U, |
KC_I, |
KC_O, |
KC_P, |
KC_LBRACKET, |
KC_RBRACKET, |
/* Main block row 3 */ |
KC_CAPS_LOCK, |
KC_A, |
KC_S, |
KC_D, |
KC_F, |
KC_G, |
KC_H, |
KC_J, |
KC_K, |
KC_L, |
KC_SEMICOLON, |
KC_QUOTE, |
KC_BACKSLASH, |
KC_ENTER, |
/* Main block row 4 */ |
KC_LSHIFT, |
KC_Z, |
KC_X, |
KC_C, |
KC_V, |
KC_B, |
KC_N, |
KC_M, |
KC_COMMA, |
KC_PERIOD, |
KC_SLASH, |
KC_RSHIFT, |
/* Main block row 5 */ |
KC_LCTRL, |
KC_LALT, |
KC_SPACE, |
KC_RALT, |
KC_RCTRL, |
/* Function keys block */ |
KC_ESCAPE, |
KC_F1, |
KC_F2, |
KC_F3, |
KC_F4, |
KC_F5, |
KC_F6, |
KC_F7, |
KC_F8, |
KC_F9, |
KC_F10, |
KC_F11, |
KC_F12, |
KC_PRTSCR, |
KC_SCROLL_LOCK, |
KC_PAUSE, |
/* Cursor keys block */ |
KC_INSERT, |
KC_HOME, |
KC_PAGE_UP, |
KC_DELETE, |
KC_END, |
KC_PAGE_DOWN, |
KC_UP, |
KC_LEFT, |
KC_DOWN, |
KC_RIGHT, |
/* Numeric block */ |
KC_NUM_LOCK, |
KC_NSLASH, |
KC_NTIMES, |
KC_NMINUS, |
KC_NPLUS, |
KC_NENTER, |
KC_N7, |
KC_N8, |
KC_N9, |
KC_N4, |
KC_N5, |
KC_N6, |
KC_N1, |
KC_N2, |
KC_N3, |
KC_N0, |
KC_NPERIOD |
} keycode_t; |
enum keymod { |
KM_LSHIFT = 0x001, |
KM_RSHIFT = 0x002, |
KM_LCTRL = 0x004, |
KM_RCTRL = 0x008, |
KM_LALT = 0x010, |
KM_RALT = 0x020, |
KM_CAPS_LOCK = 0x040, |
KM_NUM_LOCK = 0x080, |
KM_SCROLL_LOCK = 0x100, |
KM_SHIFT = KM_LSHIFT | KM_RSHIFT, |
KM_CTRL = KM_LCTRL | KM_RCTRL, |
KM_ALT = KM_LALT | KM_RALT |
} keymod_t; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/ipc/console.h |
---|
0,0 → 1,57 |
/* |
* 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 libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_CONSOLE_H_ |
#define LIBC_IPC_CONSOLE_H_ |
#include <ipc/ipc.h> |
#include <ipc/vfs.h> |
typedef enum { |
CONSOLE_GET_SIZE = VFS_OUT_LAST, |
CONSOLE_GET_COLOR_CAP, |
CONSOLE_GET_EVENT, |
CONSOLE_GOTO, |
CONSOLE_CLEAR, |
CONSOLE_SET_STYLE, |
CONSOLE_SET_COLOR, |
CONSOLE_SET_RGB_COLOR, |
CONSOLE_CURSOR_VISIBILITY, |
CONSOLE_KCON_ENABLE |
} console_request_t; |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/lib/libc/include/ipc/fb.h |
---|
41,6 → 41,7 |
FB_PUTCHAR = IPC_FIRST_USER_METHOD, |
FB_CLEAR, |
FB_GET_CSIZE, |
FB_GET_COLOR_CAP, |
FB_CURSOR_VISIBILITY, |
FB_CURSOR_GOTO, |
FB_SCROLL, |
48,10 → 49,11 |
FB_VIEWPORT_CREATE, |
FB_VIEWPORT_DELETE, |
FB_SET_STYLE, |
FB_SET_COLOR, |
FB_SET_RGB_COLOR, |
FB_GET_RESOLUTION, |
FB_DRAW_TEXT_DATA, |
FB_FLUSH, |
FB_VIEWPORT_DB, |
FB_DRAW_PPM, |
FB_PREPARE_SHM, |
FB_DROP_SHM, |
59,7 → 61,6 |
FB_VP_DRAW_PIXMAP, |
FB_VP2PIXMAP, |
FB_DROP_PIXMAP, |
FB_TRANS_PUTCHAR, |
FB_ANIM_CREATE, |
FB_ANIM_DROP, |
FB_ANIM_ADDPIXMAP, |
66,9 → 67,17 |
FB_ANIM_CHGVP, |
FB_ANIM_START, |
FB_ANIM_STOP, |
FB_POINTER_MOVE |
FB_POINTER_MOVE, |
FB_SCREEN_YIELD, |
FB_SCREEN_RECLAIM |
} fb_request_t; |
enum { |
FB_CCAP_NONE = 0, |
FB_CCAP_STYLE, |
FB_CCAP_INDEXED, |
FB_CCAP_RGB |
}; |
#endif |
/branches/arm/uspace/lib/libc/include/ipc/ns.h |
---|
35,6 → 35,15 |
#ifndef LIBIPC_NS_H_ |
#define LIBIPC_NS_H_ |
#include <ipc/ipc.h> |
typedef enum { |
NS_PING = IPC_FIRST_USER_METHOD, |
NS_TASK_WAIT, |
NS_ID_INTRO, |
NS_RETVAL |
} ns_request_t; |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/ipc/vfs.h |
---|
0,0 → 1,151 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_VFS_H_ |
#define LIBC_IPC_VFS_H_ |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#define FS_NAME_MAXLEN 20 |
#define MAX_PATH_LEN (64 * 1024) |
#define PLB_SIZE (2 * MAX_PATH_LEN) |
/* Basic types. */ |
typedef int16_t fs_handle_t; |
typedef uint32_t fs_index_t; |
/** |
* A structure like this is passed to VFS by each individual FS upon its |
* registration. It assosiates a human-readable identifier with each |
* registered FS. |
*/ |
typedef struct { |
/** Unique identifier of the fs. */ |
char name[FS_NAME_MAXLEN + 1]; |
} vfs_info_t; |
typedef enum { |
VFS_IN_OPEN = IPC_FIRST_USER_METHOD, |
VFS_IN_OPEN_NODE, |
VFS_IN_READ, |
VFS_IN_WRITE, |
VFS_IN_SEEK, |
VFS_IN_TRUNCATE, |
VFS_IN_FSTAT, |
VFS_IN_CLOSE, |
VFS_IN_MOUNT, |
VFS_IN_UNMOUNT, |
VFS_IN_SYNC, |
VFS_IN_REGISTER, |
VFS_IN_MKDIR, |
VFS_IN_UNLINK, |
VFS_IN_RENAME, |
VFS_IN_STAT |
} vfs_in_request_t; |
typedef enum { |
VFS_OUT_OPEN_NODE = IPC_FIRST_USER_METHOD, |
VFS_OUT_READ, |
VFS_OUT_WRITE, |
VFS_OUT_TRUNCATE, |
VFS_OUT_CLOSE, |
VFS_OUT_MOUNT, |
VFS_OUT_MOUNTED, |
VFS_OUT_UNMOUNT, |
VFS_OUT_SYNC, |
VFS_OUT_STAT, |
VFS_OUT_LOOKUP, |
VFS_OUT_DESTROY, |
VFS_OUT_LAST |
} vfs_out_request_t; |
/* |
* Lookup flags. |
*/ |
/** |
* No lookup flags used. |
*/ |
#define L_NONE 0 |
/** |
* Lookup will succeed only if the object is a regular file. If L_CREATE is |
* specified, an empty file will be created. This flag is mutually exclusive |
* with L_DIRECTORY. |
*/ |
#define L_FILE 1 |
/** |
* Lookup wil succeed only if the object is a directory. If L_CREATE is |
* specified, an empty directory will be created. This flag is mutually |
* exclusive with L_FILE. |
*/ |
#define L_DIRECTORY 2 |
/** |
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the |
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used. |
*/ |
#define L_EXCLUSIVE 4 |
/** |
* L_CREATE is used for creating both regular files and directories. |
*/ |
#define L_CREATE 8 |
/** |
* L_LINK is used for linking to an already existing nodes. |
*/ |
#define L_LINK 16 |
/** |
* L_UNLINK is used to remove leaves from the file system namespace. This flag |
* cannot be passed directly by the client, but will be set by VFS during |
* VFS_UNLINK. |
*/ |
#define L_UNLINK 32 |
/** |
* L_OPEN is used to indicate that the lookup operation is a part of VFS_OPEN |
* call from the client. This means that the server might allocate some |
* resources for the opened file. This flag cannot be passed directly by the |
* client. |
*/ |
#define L_OPEN 64 |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/ipc/devmap.h |
---|
28,16 → 28,19 |
/** @addtogroup devmap |
* @{ |
*/ |
*/ |
#ifndef DEVMAP_DEVMAP_H_ |
#define DEVMAP_DEVMAP_H_ |
#include <atomic.h> |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#include <adt/list.h> |
#define DEVMAP_NAME_MAXLEN 512 |
#define DEVMAP_NAME_MAXLEN 255 |
typedef ipcarg_t dev_handle_t; |
typedef enum { |
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD, |
DEVMAP_DRIVER_UNREGISTER, |
44,56 → 47,32 |
DEVMAP_DEVICE_REGISTER, |
DEVMAP_DEVICE_UNREGISTER, |
DEVMAP_DEVICE_GET_NAME, |
DEVMAP_DEVICE_GET_HANDLE |
DEVMAP_DEVICE_GET_HANDLE, |
DEVMAP_DEVICE_NULL_CREATE, |
DEVMAP_DEVICE_NULL_DESTROY, |
DEVMAP_DEVICE_GET_COUNT, |
DEVMAP_DEVICE_GET_DEVICES |
} devmap_request_t; |
/** Representation of device driver. |
* Each driver is responsible for a set of devices. |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by |
* this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
/** Interface provided by devmap. |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
int handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Interface provided by devmap. |
* Every process that connects to devmap must ask one of following |
* interfaces otherwise connection will be refused. |
* |
*/ |
typedef enum { |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
DEVMAP_CLIENT, |
/** Create new connection to instance of device that |
* is specified by second argument of call. */ |
/** Create new connection to instance of device that |
is specified by second argument of call. */ |
DEVMAP_CONNECT_TO_DEVICE |
} devmap_interface_t; |
typedef struct { |
dev_handle_t handle; |
char name[DEVMAP_NAME_MAXLEN + 1]; |
} dev_desc_t; |
#endif |
/branches/arm/uspace/lib/libc/include/ipc/ipc.h |
---|
30,25 → 30,29 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#ifndef LIBIPC_IPC_H_ |
#define LIBIPC_IPC_H_ |
#include <task.h> |
#include <kernel/ipc/ipc.h> |
#include <kernel/ddi/irq.h> |
#include <sys/types.h> |
#include <kernel/synch/synch.h> |
#define IPC_FLAG_BLOCKING 0x01 |
typedef sysarg_t ipcarg_t; |
typedef struct { |
ipcarg_t args[IPC_CALL_LEN]; |
ipcarg_t in_phone_hash; |
} ipc_call_t; |
typedef sysarg_t ipc_callid_t; |
typedef void (* ipc_async_callback_t)(void *private, int retval, |
ipc_call_t *data); |
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *); |
/* |
* User-friendly wrappers for ipc_call_sync_fast() and ipc_call_sync_slow(). |
57,49 → 61,51 |
* possible, the fast version is used. |
*/ |
#define ipc_call_sync_0_0(phoneid, method) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0) |
#define ipc_call_sync_0_1(phoneid, method, res1) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0) |
#define ipc_call_sync_0_2(phoneid, method, res1, res2) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0) |
#define ipc_call_sync_0_3(phoneid, method, res1, res2, res3) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
0, 0) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
0, 0) |
#define ipc_call_sync_0_4(phoneid, method, res1, res2, res3, res4) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
(res4), 0) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
(res4), 0) |
#define ipc_call_sync_0_5(phoneid, method, res1, res2, res3, res4, res5) \ |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
(res4), (res5)) |
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \ |
(res4), (res5)) |
#define ipc_call_sync_1_0(phoneid, method, arg1) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0) |
#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0) |
#define ipc_call_sync_1_2(phoneid, method, arg1, res1, res2) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \ |
0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \ |
0, 0) |
#define ipc_call_sync_1_3(phoneid, method, arg1, res1, res2, res3) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \ |
(res3), 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \ |
(res3), 0, 0) |
#define ipc_call_sync_1_4(phoneid, method, arg1, res1, res2, res3, res4) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \ |
(res3), (res4), 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \ |
(res3), (res4), 0) |
#define ipc_call_sync_1_5(phoneid, method, arg1, res1, res2, res3, res4, \ |
res5) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \ |
(res3), (res4), (res5)) |
#define ipc_call_sync_2_0(phoneid, method, arg1, arg2) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \ |
0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \ |
0, 0) |
#define ipc_call_sync_2_1(phoneid, method, arg1, arg2, res1) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \ |
0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \ |
0, 0) |
#define ipc_call_sync_2_2(phoneid, method, arg1, arg2, res1, res2) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
(res2), 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
(res2), 0, 0, 0) |
#define ipc_call_sync_2_3(phoneid, method, arg1, arg2, res1, res2, res3) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
(res2), (res3), 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
(res2), (res3), 0, 0) |
#define ipc_call_sync_2_4(phoneid, method, arg1, arg2, res1, res2, res3, \ |
res4) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
108,15 → 114,16 |
res4, res5)\ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \ |
(res2), (res3), (res4), (res5)) |
#define ipc_call_sync_3_0(phoneid, method, arg1, arg2, arg3) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \ |
0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \ |
0, 0) |
#define ipc_call_sync_3_1(phoneid, method, arg1, arg2, arg3, res1) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \ |
0, 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \ |
0, 0, 0, 0) |
#define ipc_call_sync_3_2(phoneid, method, arg1, arg2, arg3, res1, res2) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \ |
(res2), 0, 0, 0) |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \ |
(res2), 0, 0, 0) |
#define ipc_call_sync_3_3(phoneid, method, arg1, arg2, arg3, res1, res2, \ |
res3) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \ |
129,15 → 136,16 |
res3, res4, res5) \ |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \ |
(res1), (res2), (res3), (res4), (res5)) |
#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
0, 0, 0, 0, 0) |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
0, 0, 0, 0, 0) |
#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), 0, 0, 0, 0) |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), 0, 0, 0, 0) |
#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), (res2), 0, 0, 0) |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), (res2), 0, 0, 0) |
#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \ |
res3) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
150,12 → 158,13 |
res3, res4, res5) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), 0, (res1), (res2), (res3), (res4), (res5)) |
#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), 0, 0, 0, 0, 0) |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), 0, 0, 0, 0, 0) |
#define ipc_call_sync_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (res1), 0, 0, 0, 0) |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (res1), 0, 0, 0, 0) |
#define ipc_call_sync_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \ |
res2) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
173,23 → 182,23 |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (arg5), (res1), (res2), (res3), (res4), (res5)) |
extern int ipc_call_sync_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, |
ipcarg_t *result3, ipcarg_t *result4, ipcarg_t *result5); |
extern int ipc_call_sync_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *); |
extern int ipc_call_sync_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3, ipcarg_t *result4, |
ipcarg_t *result5); |
extern int ipc_call_sync_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *, |
ipcarg_t *); |
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags); |
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec); |
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int); |
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t); |
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data) |
{ |
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT); |
} |
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data); |
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *); |
/* |
* User-friendly wrappers for ipc_answer_fast() and ipc_answer_slow(). |
* They are in the form of ipc_answer_m(), where m is the number of return |
197,22 → 206,22 |
* to m. |
*/ |
#define ipc_answer_0(callid, retval) \ |
ipc_answer_fast((callid), (retval), 0, 0, 0, 0) |
ipc_answer_fast((callid), (retval), 0, 0, 0, 0) |
#define ipc_answer_1(callid, retval, arg1) \ |
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0) |
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0) |
#define ipc_answer_2(callid, retval, arg1, arg2) \ |
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0) |
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0) |
#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \ |
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0) |
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0) |
#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \ |
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4)) |
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4)) |
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \ |
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5)) |
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5)) |
extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4); |
extern ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5); |
extern ipcarg_t ipc_answer_fast(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t); |
extern ipcarg_t ipc_answer_slow(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t); |
/* |
* User-friendly wrappers for ipc_call_async_fast() and ipc_call_async_slow(). |
220,8 → 229,7 |
* arguments. The macros decide between the fast and the slow version according |
* to m. |
*/ |
#define ipc_call_async_0(phoneid, method, private, callback, \ |
can_preempt) \ |
#define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \ |
ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \ |
(callback), (can_preempt)) |
#define ipc_call_async_1(phoneid, method, arg1, private, callback, \ |
245,53 → 253,48 |
ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (arg5), (private), (callback), (can_preempt)) |
extern void ipc_call_async_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, void *private, |
ipc_async_callback_t callback, int can_preempt); |
extern void ipc_call_async_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, void *private, |
ipc_async_callback_t callback, int can_preempt); |
extern void ipc_call_async_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, void *, ipc_async_callback_t, int); |
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int); |
extern int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, |
ipcarg_t *phone); |
extern int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3); |
extern int ipc_hangup(int phoneid); |
extern int ipc_register_irq(int inr, int devno, int method, irq_code_t *code); |
extern int ipc_unregister_irq(int inr, int devno); |
extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, |
ipcarg_t arg1, ipcarg_t arg2, int mode); |
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *); |
extern int ipc_connect_me_to(int, int, int, int); |
extern int ipc_connect_me_to_blocking(int, int, int, int); |
extern int ipc_hangup(int); |
extern int ipc_register_irq(int, int, int, irq_code_t *); |
extern int ipc_unregister_irq(int, int); |
extern int ipc_forward_fast(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, int); |
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t, int); |
/* |
* User-friendly wrappers for ipc_share_in_start(). |
*/ |
#define ipc_share_in_start_0_0(phoneid, dst, size) \ |
ipc_share_in_start((phoneid), (dst), (size), 0, NULL) |
ipc_share_in_start((phoneid), (dst), (size), 0, NULL) |
#define ipc_share_in_start_0_1(phoneid, dst, size, flags) \ |
ipc_share_in_start((phoneid), (dst), (size), 0, (flags)) |
ipc_share_in_start((phoneid), (dst), (size), 0, (flags)) |
#define ipc_share_in_start_1_0(phoneid, dst, size, arg) \ |
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL) |
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL) |
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \ |
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags)) |
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags)) |
extern int ipc_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg, |
int *flags); |
extern int ipc_share_in_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags); |
extern int ipc_share_out_start(int phoneid, void *src, int flags); |
extern int ipc_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags); |
extern int ipc_share_out_finalize(ipc_callid_t callid, void *dst); |
extern int ipc_data_read_start(int phoneid, void *dst, size_t size); |
extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size); |
extern int ipc_data_write_start(int phoneid, void *src, size_t size); |
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size); |
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *); |
extern int ipc_share_in_receive(ipc_callid_t *, size_t *); |
extern int ipc_share_in_finalize(ipc_callid_t, void *, int ); |
extern int ipc_share_out_start(int, void *, int); |
extern int ipc_share_out_receive(ipc_callid_t *, size_t *, int *); |
extern int ipc_share_out_finalize(ipc_callid_t, void *); |
extern int ipc_data_read_start(int, void *, size_t); |
extern int ipc_data_read_receive(ipc_callid_t *, size_t *); |
extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t); |
extern int ipc_data_write_start(int, const void *, size_t); |
extern int ipc_data_write_receive(ipc_callid_t *, size_t *); |
extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t); |
#include <task.h> |
extern int ipc_connect_kbox(task_id_t); |
extern int ipc_connect_kbox(task_id_t id); |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/ipc/loader.h |
---|
42,9 → 42,10 |
LOADER_GET_TASKID, |
LOADER_SET_PATHNAME, |
LOADER_SET_ARGS, |
LOADER_SET_FILES, |
LOADER_LOAD, |
LOADER_RUN |
} fb_request_t; |
} loader_request_t; |
#endif |
/branches/arm/uspace/lib/libc/include/ipc/bd.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_BD_H_ |
#define LIBC_IPC_BD_H_ |
#include <ipc/ipc.h> |
typedef enum { |
BD_READ_BLOCK = IPC_FIRST_USER_METHOD, |
BD_WRITE_BLOCK |
} bd_request_t; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/ipc/services.h |
---|
30,8 → 30,8 |
* @{ |
*/ |
/** |
* @file services.h |
* @brief List of all known services and their codes. |
* @file services.h |
* @brief List of all known services and their codes. |
*/ |
#ifndef LIBIPC_SERVICES_H_ |
38,12 → 38,15 |
#define LIBIPC_SERVICES_H_ |
typedef enum { |
SERVICE_PCI = 1, |
SERVICE_LOAD = 1, |
SERVICE_PCI, |
SERVICE_KEYBOARD, |
SERVICE_VIDEO, |
SERVICE_CONSOLE, |
SERVICE_VFS, |
SERVICE_DEVMAP |
SERVICE_DEVMAP, |
SERVICE_FHC, |
SERVICE_OBIO |
} services_t; |
/* Memory area to be received from NS */ |
/branches/arm/uspace/lib/libc/include/ipc/bus.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_BUS_H_ |
#define LIBC_BUS_H_ |
#include <ipc/ipc.h> |
typedef enum { |
BUS_CLEAR_INTERRUPT = IPC_FIRST_USER_METHOD |
} bus_request_t; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/fibril.h |
---|
36,17 → 36,18 |
#define LIBC_FIBRIL_H_ |
#include <libarch/fibril.h> |
#include <libadt/list.h> |
#include <adt/list.h> |
#include <libarch/tls.h> |
#ifndef context_set |
#define context_set(c, _pc, stack, size, ptls) \ |
(c)->pc = (sysarg_t) (_pc); \ |
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \ |
(c)->tls = (sysarg_t) (ptls); |
#define context_set(c, _pc, stack, size, ptls) \ |
(c)->pc = (sysarg_t) (_pc); \ |
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \ |
(c)->tls = (sysarg_t) (ptls); |
#endif /* context_set */ |
#define FIBRIL_SERIALIZED 1 |
#define FIBRIL_SERIALIZED 1 |
#define FIBRIL_WRITER 2 |
typedef enum { |
FIBRIL_PREEMPT, |
71,7 → 72,10 |
}; |
typedef struct fibril fibril_t; |
extern int context_save(context_t *c); |
/** Fibril-local variable specifier */ |
#define fibril_local __thread |
extern int context_save(context_t *c) __attribute__ ((returns_twice)); |
extern void context_restore(context_t *c) __attribute__ ((noreturn)); |
extern fid_t fibril_create(int (*func)(void *), void *arg); |
/branches/arm/uspace/lib/libc/include/task.h |
---|
39,9 → 39,18 |
typedef uint64_t task_id_t; |
typedef enum { |
TASK_EXIT_NORMAL, |
TASK_EXIT_UNEXPECTED |
} task_exit_t; |
extern task_id_t task_get_id(void); |
extern int task_set_name(const char *name); |
extern task_id_t task_spawn(const char *path, char *const argv[]); |
extern int task_wait(task_id_t id, task_exit_t *texit, int *retval); |
extern int task_retval(int val); |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/getopt.h |
---|
58,7 → 58,7 |
}; |
/* HelenOS Port - These need to be exposed for legacy getopt() */ |
extern char *optarg; |
extern const char *optarg; |
extern int optind, opterr, optopt; |
extern int optreset; |
/branches/arm/uspace/lib/libc/include/vfs/vfs.h |
---|
36,11 → 36,36 |
#define LIBC_VFS_H_ |
#include <sys/types.h> |
#include <ipc/vfs.h> |
#include <ipc/devmap.h> |
#include <stdio.h> |
/** |
* This type is a libc version of the VFS triplet. |
* It uniquelly identifies a file system node within a file system instance. |
*/ |
typedef struct { |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
fs_index_t index; |
} fdi_node_t; |
extern char *absolutize(const char *, size_t *); |
extern int mount(const char *, const char *, const char *); |
extern int mount(const char *, const char *, const char *, const char *, |
unsigned int); |
extern void __stdio_init(int filc, fdi_node_t *filv[]); |
extern void __stdio_done(void); |
extern int open_node(fdi_node_t *, int); |
extern int fd_phone(int); |
extern int fd_node(int, fdi_node_t *); |
extern FILE *fopen_node(fdi_node_t *, const char *); |
extern int fphone(FILE *); |
extern int fnode(FILE *, fdi_node_t *); |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/async.h |
---|
44,17 → 44,21 |
typedef ipc_callid_t aid_t; |
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call); |
static inline void async_manager(void) |
{ |
fibril_switch(FIBRIL_TO_MANAGER); |
} |
extern atomic_t async_futex; |
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs); |
extern int __async_init(void); |
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs); |
static inline ipc_callid_t async_get_call(ipc_call_t *data) |
{ |
return async_get_call_timeout(data, 0); |
} |
static inline void async_manager(void) |
{ |
fibril_switch(FIBRIL_TO_MANAGER); |
} |
/* |
* User-friendly wrappers for async_send_fast() and async_send_slow(). The |
* macros are in the form async_send_m(), where m denotes the number of payload |
63,20 → 67,20 |
*/ |
#define async_send_0(phoneid, method, dataptr) \ |
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr)) |
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr)) |
#define async_send_1(phoneid, method, arg1, dataptr) \ |
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr)) |
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr)) |
#define async_send_2(phoneid, method, arg1, arg2, dataptr) \ |
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr)) |
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr)) |
#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \ |
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr)) |
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr)) |
#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \ |
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(dataptr)) |
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(dataptr)) |
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \ |
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (dataptr)) |
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (dataptr)) |
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr); |
extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
86,12 → 90,11 |
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, |
suseconds_t timeout); |
fid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid, |
ipc_call_t *call, void (*cthread)(ipc_callid_t,ipc_call_t *)); |
void async_usleep(suseconds_t timeout); |
void async_create_manager(void); |
void async_destroy_manager(void); |
int _async_init(void); |
extern fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *)); |
extern void async_usleep(suseconds_t timeout); |
extern void async_create_manager(void); |
extern void async_destroy_manager(void); |
extern void async_set_client_connection(async_client_conn_t conn); |
extern void async_set_interrupt_received(async_client_conn_t conn); |
98,114 → 101,114 |
/* Wrappers for simple communication */ |
#define async_msg_0(phone, method) \ |
ipc_call_async_0((phone), (method), NULL, NULL, !in_interrupt_handler()) |
ipc_call_async_0((phone), (method), NULL, NULL, true) |
#define async_msg_1(phone, method, arg1) \ |
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \ |
!in_interrupt_handler()) |
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \ |
true) |
#define async_msg_2(phone, method, arg1, arg2) \ |
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \ |
!in_interrupt_handler()) |
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \ |
true) |
#define async_msg_3(phone, method, arg1, arg2, arg3) \ |
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \ |
!in_interrupt_handler()) |
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \ |
true) |
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \ |
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, !in_interrupt_handler()) |
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, true) |
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \ |
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, !in_interrupt_handler()) |
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, true) |
/* |
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros |
* are in the form async_req_m_n(), where m is the number of payload arguments |
* and n is the number of return arguments. The macros decidce between the fast |
* and n is the number of return arguments. The macros decide between the fast |
* and slow verion based on m. |
*/ |
#define async_req_0_0(phoneid, method) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \ |
NULL) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \ |
NULL) |
#define async_req_0_1(phoneid, method, r1) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \ |
NULL) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \ |
NULL) |
#define async_req_0_2(phoneid, method, r1, r2) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \ |
NULL) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \ |
NULL) |
#define async_req_0_3(phoneid, method, r1, r2, r3) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \ |
NULL) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \ |
NULL) |
#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \ |
NULL) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \ |
NULL) |
#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \ |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \ |
(r5)) |
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \ |
(r5)) |
#define async_req_1_0(phoneid, method, arg1) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \ |
NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \ |
NULL, NULL) |
#define async_req_1_1(phoneid, method, arg1, rc1) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \ |
NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \ |
NULL, NULL) |
#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \ |
NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \ |
NULL, NULL) |
#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
NULL, NULL) |
#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
(rc4), NULL) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
(rc4), NULL) |
#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \ |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
(rc4), (rc5)) |
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \ |
(rc4), (rc5)) |
#define async_req_2_0(phoneid, method, arg1, arg2) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \ |
NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \ |
NULL, NULL, NULL) |
#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \ |
NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \ |
NULL, NULL, NULL) |
#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
NULL, NULL, NULL) |
#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), NULL, NULL) |
#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), (rc4), NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), (rc4), NULL) |
#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), (rc4), (rc5)) |
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \ |
(rc3), (rc4), (rc5)) |
#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \ |
NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \ |
NULL, NULL, NULL) |
#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
NULL, NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
NULL, NULL, NULL, NULL) |
#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), NULL, NULL, NULL) |
#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), (rc3), NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), (rc3), NULL, NULL) |
#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), (rc3), (rc4), NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), (rc3), (rc4), NULL) |
#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \ |
rc5) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \ |
(rc2), (rc3), (rc4), (rc5)) |
#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, NULL, NULL, NULL) |
#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
NULL, NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
NULL, NULL, NULL, NULL) |
#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
(rc2), NULL, NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
(rc2), NULL, NULL, NULL) |
#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
(rc2), (rc3), NULL, NULL) |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \ |
(rc2), (rc3), NULL, NULL) |
#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \ |
rc4) \ |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
215,14 → 218,14 |
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(rc1), (rc2), (rc3), (rc4), (rc5)) |
#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \ |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, NULL, NULL, NULL) |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, NULL, NULL, NULL) |
#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \ |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (rc1), NULL, NULL, NULL, NULL) |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (rc1), NULL, NULL, NULL, NULL) |
#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \ |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (rc1), (rc2), NULL, NULL, NULL) |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (rc1), (rc2), NULL, NULL, NULL) |
#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \ |
rc3) \ |
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
253,10 → 256,6 |
fibril_dec_sercount(); |
} |
extern bool in_interrupt_handler(void); |
extern atomic_t async_futex; |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/stdlib.h |
---|
38,10 → 38,10 |
#include <unistd.h> |
#include <malloc.h> |
#define abort() _exit(1) |
#define exit(status) _exit((status)) |
#define abort() _exit(1) |
#define exit(status) _exit((status)) |
#define RAND_MAX 714025 |
#define RAND_MAX 714025 |
extern long int random(void); |
extern void srandom(unsigned int seed); |
50,6 → 50,7 |
{ |
return random(); |
} |
static inline void srand(unsigned int seed) |
{ |
srandom(seed); |
/branches/arm/uspace/lib/libc/include/stdio.h |
---|
37,37 → 37,115 |
#include <sys/types.h> |
#include <stdarg.h> |
#include <string.h> |
#include <adt/list.h> |
#define EOF (-1) |
#define EOF (-1) |
#include <string.h> |
#include <io/stream.h> |
/** Default size for stream I/O buffers */ |
#define BUFSIZ 4096 |
#define DEBUG(fmt, ...) \ |
{ \ |
char buf[256]; \ |
int n; \ |
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \ |
if (n > 0) \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, strlen(buf)); \ |
} |
{ \ |
char _buf[256]; \ |
int _n = snprintf(_buf, sizeof(_buf), fmt, ##__VA_ARGS__); \ |
if (_n > 0) \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) _buf, str_size(_buf)); \ |
} |
#ifndef SEEK_SET |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#endif |
enum _buffer_type { |
/** No buffering */ |
_IONBF, |
/** Line buffering */ |
_IOLBF, |
/** Full buffering */ |
_IOFBF |
}; |
typedef struct { |
/** Linked list pointer. */ |
link_t link; |
/** Underlying file descriptor. */ |
int fd; |
/** Error indicator. */ |
int error; |
/** End-of-file indicator. */ |
int eof; |
/** Klog indicator */ |
int klog; |
/** Phone to the file provider */ |
int phone; |
/** Buffering type */ |
enum _buffer_type btype; |
/** Buffer */ |
uint8_t *buf; |
/** Buffer size */ |
size_t buf_size; |
/** Buffer I/O pointer */ |
uint8_t *buf_head; |
} FILE; |
extern FILE *stdin; |
extern FILE *stdout; |
extern FILE *stderr; |
/* Character and string input functions */ |
extern int fgetc(FILE *); |
extern char *fgets(char *, size_t, FILE *); |
extern int getchar(void); |
extern char *gets(char *, size_t); |
/* Character and string output functions */ |
extern int fputc(wchar_t, FILE *); |
extern int fputs(const char *, FILE *); |
extern int putchar(wchar_t); |
extern int puts(const char *); |
extern int putchar(int); |
/* Formatted string output functions */ |
extern int fprintf(FILE *, const char*, ...); |
extern int vfprintf(FILE *, const char *, va_list); |
extern int printf(const char *, ...); |
extern int vprintf(const char *, va_list); |
extern int snprintf(char *, size_t , const char *, ...); |
extern int asprintf(char **, const char *, ...); |
extern int sprintf(char *, const char *fmt, ...); |
extern int snprintf(char *, size_t , const char *, ...); |
extern int vprintf(const char *, va_list); |
extern int vsprintf(char *, const char *, va_list); |
extern int vsnprintf(char *, size_t, const char *, va_list); |
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__) |
/* File stream functions */ |
extern FILE *fopen(const char *, const char *); |
extern FILE *fdopen(int, const char *); |
extern int fclose(FILE *); |
extern size_t fread(void *, size_t, size_t, FILE *); |
extern size_t fwrite(const void *, size_t, size_t, FILE *); |
extern int fseek(FILE *, long, int); |
extern void rewind(FILE *); |
extern int ftell(FILE *); |
extern int feof(FILE *); |
extern int fflush(FILE *); |
extern int ferror(FILE *); |
extern void clearerr(FILE *); |
extern void setvbuf(FILE *, void *, int, size_t); |
/* Misc file functions */ |
extern int rename(const char *, const char *); |
#endif |
/branches/arm/uspace/lib/libc/include/bitops.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
42,10 → 42,10 |
* |
* If number is zero, it returns 0 |
*/ |
static inline int fnzb32(uint32_t arg) |
static inline unsigned int fnzb32(uint32_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 16) { |
arg >>= 16; |
n += 16; |
74,19 → 74,22 |
return n; |
} |
static inline int fnzb64(uint64_t arg) |
static inline unsigned int fnzb64(uint64_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 32) { |
arg >>= 32; |
n += 32; |
} |
return n + fnzb32((uint32_t) arg); |
return (n + fnzb32((uint32_t) arg)); |
} |
#define fnzb(x) fnzb32(x) |
static inline unsigned int fnzb(size_t arg) |
{ |
return fnzb64(arg); |
} |
#endif |
/branches/arm/uspace/lib/libc/include/unistd.h |
---|
39,27 → 39,32 |
#include <libarch/config.h> |
#ifndef NULL |
#define NULL 0 |
#define NULL 0 |
#endif |
#define getpagesize() (PAGE_SIZE) |
#define getpagesize() (PAGE_SIZE) |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#ifndef SEEK_SET |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#endif |
extern ssize_t write(int, const void *, size_t); |
extern ssize_t read(int, void *, size_t); |
extern off_t lseek(int, off_t, int); |
extern int ftruncate(int, off_t); |
extern int close(int); |
extern int fsync(int); |
extern int unlink(const char *); |
extern char *getcwd(char *buf, size_t); |
extern int rmdir(const char *); |
extern int chdir(const char *); |
extern char *getcwd(char *buf, size_t); |
extern void _exit(int status); |
extern void *sbrk(ssize_t incr); |
extern void _exit(int status) __attribute__ ((noreturn)); |
extern int usleep(unsigned long usec); |
extern unsigned int sleep(unsigned int seconds); |
/branches/arm/uspace/lib/libc/include/mem.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2005 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_MEM_H_ |
#define LIBC_MEM_H_ |
#include <sys/types.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
extern void *memset(void *, int, size_t); |
extern void *memcpy(void *, const void *, size_t); |
extern void *memmove(void *, const void *, size_t); |
extern int bcmp(const char *, const char *, size_t); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/lib/libc/include/adt/gcdlcm.h |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_GCDLCM_H_ |
#define LIBC_GCDLCM_H_ |
#include <sys/types.h> |
#define DECLARE_GCD(type, name) \ |
static inline type name(type a, type b) \ |
{ \ |
if (a == 0) \ |
return b; \ |
\ |
while (b != 0) { \ |
if (a > b) \ |
a -= b; \ |
else \ |
b -= a; \ |
} \ |
\ |
return a; \ |
} |
#define DECLARE_LCM(type, name, gcd) \ |
static inline type name(type a, type b) \ |
{ \ |
return (a * b) / gcd(a, b); \ |
} |
DECLARE_GCD(uint32_t, gcd32); |
DECLARE_GCD(uint64_t, gcd64); |
DECLARE_GCD(size_t, gcd); |
DECLARE_LCM(uint32_t, lcm32, gcd32); |
DECLARE_LCM(uint64_t, lcm64, gcd64); |
DECLARE_LCM(size_t, lcm, gcd); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/adt/hash_table.h |
---|
0,0 → 1,94 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_HASH_TABLE_H_ |
#define LIBC_HASH_TABLE_H_ |
#include <adt/list.h> |
#include <unistd.h> |
typedef unsigned long hash_count_t; |
typedef unsigned long hash_index_t; |
typedef struct hash_table hash_table_t; |
typedef struct hash_table_operations hash_table_operations_t; |
/** Hash table structure. */ |
struct hash_table { |
link_t *entry; |
hash_count_t entries; |
hash_count_t max_keys; |
hash_table_operations_t *op; |
}; |
/** Set of operations for hash table. */ |
struct hash_table_operations { |
/** Hash function. |
* |
* @param key Array of keys needed to compute hash index. All keys |
* must be passed. |
* |
* @return Index into hash table. |
*/ |
hash_index_t (* hash)(unsigned long key[]); |
/** Hash table item comparison function. |
* |
* @param key Array of keys that will be compared with item. It is |
* not necessary to pass all keys. |
* |
* @return true if the keys match, false otherwise. |
*/ |
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item); |
/** Hash table item removal callback. |
* |
* @param item Item that was removed from the hash table. |
*/ |
void (*remove_callback)(link_t *item); |
}; |
#define hash_table_get_instance(item, type, member) \ |
list_get_instance((item), type, member) |
extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t, |
hash_table_operations_t *); |
extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *); |
extern link_t *hash_table_find(hash_table_t *, unsigned long []); |
extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t); |
extern void hash_table_destroy(hash_table_t *); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/adt/list.h |
---|
0,0 → 1,201 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_LIST_H_ |
#define LIBC_LIST_H_ |
#include <unistd.h> |
/** Doubly linked list head and link type. */ |
typedef struct link { |
struct link *prev; /**< Pointer to the previous item in the list. */ |
struct link *next; /**< Pointer to the next item in the list. */ |
} link_t; |
/** Declare and initialize statically allocated list. |
* |
* @param name Name of the new statically allocated list. |
*/ |
#define LIST_INITIALIZE(name) link_t name = { \ |
.prev = &name, \ |
.next = &name \ |
} |
/** Initialize doubly-linked circular list link |
* |
* Initialize doubly-linked list link. |
* |
* @param link Pointer to link_t structure to be initialized. |
*/ |
static inline void link_initialize(link_t *link) |
{ |
link->prev = NULL; |
link->next = NULL; |
} |
/** Initialize doubly-linked circular list |
* |
* Initialize doubly-linked circular list. |
* |
* @param head Pointer to link_t structure representing head of the list. |
*/ |
static inline void list_initialize(link_t *head) |
{ |
head->prev = head; |
head->next = head; |
} |
/** Add item to the beginning of doubly-linked circular list |
* |
* Add item to the beginning of doubly-linked circular list. |
* |
* @param link Pointer to link_t structure to be added. |
* @param head Pointer to link_t structure representing head of the list. |
*/ |
static inline void list_prepend(link_t *link, link_t *head) |
{ |
link->next = head->next; |
link->prev = head; |
head->next->prev = link; |
head->next = link; |
} |
/** Add item to the end of doubly-linked circular list |
* |
* Add item to the end of doubly-linked circular list. |
* |
* @param link Pointer to link_t structure to be added. |
* @param head Pointer to link_t structure representing head of the list. |
*/ |
static inline void list_append(link_t *link, link_t *head) |
{ |
link->prev = head->prev; |
link->next = head; |
head->prev->next = link; |
head->prev = link; |
} |
/** Insert item before another item in doubly-linked circular list. */ |
static inline void list_insert_before(link_t *l, link_t *r) |
{ |
list_append(l, r); |
} |
/** Insert item after another item in doubly-linked circular list. */ |
static inline void list_insert_after(link_t *r, link_t *l) |
{ |
list_prepend(l, r); |
} |
/** Remove item from doubly-linked circular list |
* |
* Remove item from doubly-linked circular list. |
* |
* @param link Pointer to link_t structure to be removed from the list it is contained in. |
*/ |
static inline void list_remove(link_t *link) |
{ |
link->next->prev = link->prev; |
link->prev->next = link->next; |
link_initialize(link); |
} |
/** Query emptiness of doubly-linked circular list |
* |
* Query emptiness of doubly-linked circular list. |
* |
* @param head Pointer to link_t structure representing head of the list. |
*/ |
static inline int list_empty(link_t *head) |
{ |
return ((head->next == head) ? 1 : 0); |
} |
/** Split or concatenate headless doubly-linked circular list |
* |
* Split or concatenate headless doubly-linked circular list. |
* |
* Note that the algorithm works both directions: |
* concatenates splitted lists and splits concatenated lists. |
* |
* @param part1 Pointer to link_t structure leading the first (half of the headless) list. |
* @param part2 Pointer to link_t structure leading the second (half of the headless) list. |
*/ |
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2) |
{ |
part1->prev->next = part2; |
part2->prev->next = part1; |
link_t *hlp = part1->prev; |
part1->prev = part2->prev; |
part2->prev = hlp; |
} |
/** Split headless doubly-linked circular list |
* |
* Split headless doubly-linked circular list. |
* |
* @param part1 Pointer to link_t structure leading the first half of the headless list. |
* @param part2 Pointer to link_t structure leading the second half of the headless list. |
*/ |
static inline void headless_list_split(link_t *part1, link_t *part2) |
{ |
headless_list_split_or_concat(part1, part2); |
} |
/** Concatenate two headless doubly-linked circular lists |
* |
* Concatenate two headless doubly-linked circular lists. |
* |
* @param part1 Pointer to link_t structure leading the first headless list. |
* @param part2 Pointer to link_t structure leading the second headless list. |
*/ |
static inline void headless_list_concat(link_t *part1, link_t *part2) |
{ |
headless_list_split_or_concat(part1, part2); |
} |
#define list_get_instance(link, type, member) ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member)))) |
extern int list_member(const link_t *link, const link_t *head); |
extern void list_concat(link_t *head1, link_t *head2); |
extern unsigned int list_count(const link_t *link); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/adt/fifo.h |
---|
0,0 → 1,127 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
/* |
* This implementation of FIFO stores values in an array |
* (static or dynamic). As such, these FIFOs have upper bound |
* on number of values they can store. Push and pop operations |
* are done via accessing the array through head and tail indices. |
* Because of better operation ordering in fifo_pop(), the access |
* policy for these two indices is to 'increment (mod size of FIFO) |
* and use'. |
*/ |
#ifndef LIBC_FIFO_H_ |
#define LIBC_FIFO_H_ |
#include <malloc.h> |
typedef unsigned long fifo_count_t; |
typedef unsigned long fifo_index_t; |
#define FIFO_CREATE_STATIC(name, t, itms) \ |
struct { \ |
t fifo[(itms)]; \ |
fifo_count_t items; \ |
fifo_index_t head; \ |
fifo_index_t tail; \ |
} name |
/** Create and initialize static FIFO. |
* |
* FIFO is allocated statically. |
* This macro is suitable for creating smaller FIFOs. |
* |
* @param name Name of FIFO. |
* @param t Type of values stored in FIFO. |
* @param itms Number of items that can be stored in FIFO. |
*/ |
#define FIFO_INITIALIZE_STATIC(name, t, itms) \ |
FIFO_CREATE_STATIC(name, t, itms) = { \ |
.items = (itms), \ |
.head = 0, \ |
.tail = 0 \ |
} |
/** Create and prepare dynamic FIFO. |
* |
* FIFO is allocated dynamically. |
* This macro is suitable for creating larger FIFOs. |
* |
* @param name Name of FIFO. |
* @param t Type of values stored in FIFO. |
* @param itms Number of items that can be stored in FIFO. |
*/ |
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \ |
struct { \ |
t *fifo; \ |
fifo_count_t items; \ |
fifo_index_t head; \ |
fifo_index_t tail; \ |
} name = { \ |
.fifo = NULL, \ |
.items = (itms), \ |
.head = 0, \ |
.tail = 0 \ |
} |
/** Pop value from head of FIFO. |
* |
* @param name FIFO name. |
* |
* @return Leading value in FIFO. |
*/ |
#define fifo_pop(name) \ |
name.fifo[name.head = (name.head + 1) < name.items ? (name.head + 1) : 0] |
/** Push value to tail of FIFO. |
* |
* @param name FIFO name. |
* @param value Value to be appended to FIFO. |
* |
*/ |
#define fifo_push(name, value) \ |
name.fifo[name.tail = (name.tail + 1) < name.items ? (name.tail + 1) : 0] = (value) |
/** Allocate memory for dynamic FIFO. |
* |
* @param name FIFO name. |
*/ |
#define fifo_create(name) \ |
name.fifo = malloc(sizeof(*name.fifo) * name.items) |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/macros.h |
---|
0,0 → 1,60 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_MACROS_H_ |
#define LIBC_MACROS_H_ |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
#define KB2SIZE(kb) ((kb) << 10) |
#define MB2SIZE(mb) ((mb) << 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
#define LOWER32(arg) ((arg) & 0xffffffff) |
#define UPPER32(arg) (((arg) >> 32) & 0xffffffff) |
#define MERGE_LOUP32(lo, up) \ |
((((uint64_t) (lo)) & 0xffffffff) \ |
| ((((uint64_t) (up)) & 0xffffffff) << 32)) |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/errno.h |
---|
36,17 → 36,25 |
#define LIBC_ERRNO_H_ |
#include <kernel/errno.h> |
#include <fibril.h> |
#define ENAMETOOLONG (-256) |
#define EISDIR (-257) |
#define ENOTDIR (-258) |
#define ENOSPC (-259) |
#define EEXIST (-260) |
#define ENOTEMPTY (-261) |
#define EBADF (-262) |
#define ERANGE (-263) |
#define EXDEV (-264) |
extern int _errno; |
#define errno _errno |
#define EMFILE (-17) |
#define ENAMETOOLONG (-256) |
#define EISDIR (-257) |
#define ENOTDIR (-258) |
#define ENOSPC (-259) |
#define EEXIST (-260) |
#define ENOTEMPTY (-261) |
#define EBADF (-262) |
#define ERANGE (-263) |
#define EXDEV (-264) |
#define EIO (-265) |
#define EMLINK (-266) |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/malloc.h |
---|
1,537 → 1,51 |
/* |
Default header file for malloc-2.8.x, written by Doug Lea |
and released to the public domain, as explained at |
http://creativecommons.org/licenses/publicdomain. |
last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee) |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
This header is for ANSI C/C++ only. You can set any of |
the following #defines before including: |
* If USE_DL_PREFIX is defined, it is assumed that malloc.c |
was also compiled with this option, so all routines |
have names starting with "dl". |
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this |
file will be #included AFTER <malloc.h>. This is needed only if |
your system defines a struct mallinfo that is incompatible with the |
standard one declared here. Otherwise, you can include this file |
INSTEAD of your system system <malloc.h>. At least on ANSI, all |
declarations should be compatible with system versions |
* If MSPACES is defined, declarations for mspace versions are included. |
*/ |
#ifndef MALLOC_280_H |
#define MALLOC_280_H |
#ifdef __cplusplus |
extern "C" { |
#endif |
#include <stddef.h> /* for size_t */ |
#if !ONLY_MSPACES |
#ifndef USE_DL_PREFIX |
#define dlcalloc calloc |
#define dlfree free |
#define dlmalloc malloc |
#define dlmemalign memalign |
#define dlrealloc realloc |
#define dlvalloc valloc |
#define dlpvalloc pvalloc |
#define dlmallinfo mallinfo |
#define dlmallopt mallopt |
#define dlmalloc_trim malloc_trim |
#define dlmalloc_stats malloc_stats |
#define dlmalloc_usable_size malloc_usable_size |
#define dlmalloc_footprint malloc_footprint |
#define dlmalloc_max_footprint malloc_max_footprint |
#define dlindependent_calloc independent_calloc |
#define dlindependent_comalloc independent_comalloc |
#endif /* USE_DL_PREFIX */ |
/* |
malloc(size_t n) |
Returns a pointer to a newly allocated chunk of at least n bytes, or |
null if no space is available, in which case errno is set to ENOMEM |
on ANSI C systems. |
If n is zero, malloc returns a minimum-sized chunk. (The minimum |
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit |
systems.) Note that size_t is an unsigned type, so calls with |
arguments that would be negative if signed are interpreted as |
requests for huge amounts of space, which will often fail. The |
maximum supported value of n differs across systems, but is in all |
cases less than the maximum representable value of a size_t. |
*/ |
void* dlmalloc(size_t); |
/* |
free(void* p) |
Releases the chunk of memory pointed to by p, that had been previously |
allocated using malloc or a related routine such as realloc. |
It has no effect if p is null. If p was not malloced or already |
freed, free(p) will by default cuase the current program to abort. |
*/ |
void dlfree(void*); |
/* |
calloc(size_t n_elements, size_t element_size); |
Returns a pointer to n_elements * element_size bytes, with all locations |
set to zero. |
*/ |
void* dlcalloc(size_t, size_t); |
/* |
realloc(void* p, size_t n) |
Returns a pointer to a chunk of size n that contains the same data |
as does chunk p up to the minimum of (n, p's size) bytes, or null |
if no space is available. |
The returned pointer may or may not be the same as p. The algorithm |
prefers extending p in most cases when possible, otherwise it |
employs the equivalent of a malloc-copy-free sequence. |
If p is null, realloc is equivalent to malloc. |
If space is not available, realloc returns null, errno is set (if on |
ANSI) and p is NOT freed. |
if n is for fewer bytes than already held by p, the newly unused |
space is lopped off and freed if possible. realloc with a size |
argument of zero (re)allocates a minimum-sized chunk. |
The old unix realloc convention of allowing the last-free'd chunk |
to be used as an argument to realloc is not supported. |
*/ |
void* dlrealloc(void*, size_t); |
/* |
memalign(size_t alignment, size_t n); |
Returns a pointer to a newly allocated chunk of n bytes, aligned |
in accord with the alignment argument. |
The alignment argument should be a power of two. If the argument is |
not a power of two, the nearest greater power is used. |
8-byte alignment is guaranteed by normal malloc calls, so don't |
bother calling memalign with an argument of 8 or less. |
Overreliance on memalign is a sure way to fragment space. |
*/ |
void* dlmemalign(size_t, size_t); |
/* |
valloc(size_t n); |
Equivalent to memalign(pagesize, n), where pagesize is the page |
size of the system. If the pagesize is unknown, 4096 is used. |
*/ |
void* dlvalloc(size_t); |
/* |
mallopt(int parameter_number, int parameter_value) |
Sets tunable parameters The format is to provide a |
(parameter-number, parameter-value) pair. mallopt then sets the |
corresponding parameter to the argument value if it can (i.e., so |
long as the value is meaningful), and returns 1 if successful else |
0. SVID/XPG/ANSI defines four standard param numbers for mallopt, |
normally defined in malloc.h. None of these are use in this malloc, |
so setting them has no effect. But this malloc also supports other |
options in mallopt: |
Symbol param # default allowed param values |
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming) |
M_GRANULARITY -2 page size any power of 2 >= page size |
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) |
*/ |
int dlmallopt(int, int); |
#define M_TRIM_THRESHOLD (-1) |
#define M_GRANULARITY (-2) |
#define M_MMAP_THRESHOLD (-3) |
/* |
malloc_footprint(); |
Returns the number of bytes obtained from the system. The total |
number of bytes allocated by malloc, realloc etc., is less than this |
value. Unlike mallinfo, this function returns only a precomputed |
result, so can be called frequently to monitor memory consumption. |
Even if locks are otherwise defined, this function does not use them, |
so results might not be up to date. |
*/ |
size_t dlmalloc_footprint(void); |
size_t dlmalloc_max_footprint(void); |
#if !NO_MALLINFO |
/* |
mallinfo() |
Returns (by copy) a struct containing various summary statistics: |
arena: current total non-mmapped bytes allocated from system |
ordblks: the number of free chunks |
smblks: always zero. |
hblks: current number of mmapped regions |
hblkhd: total bytes held in mmapped regions |
usmblks: the maximum total allocated space. This will be greater |
than current total if trimming has occurred. |
fsmblks: always zero |
uordblks: current total allocated space (normal or mmapped) |
fordblks: total free space |
keepcost: the maximum number of bytes that could ideally be released |
back to system via malloc_trim. ("ideally" means that |
it ignores page restrictions etc.) |
Because these fields are ints, but internal bookkeeping may |
be kept as longs, the reported values may wrap around zero and |
thus be inaccurate. |
*/ |
#ifndef HAVE_USR_INCLUDE_MALLOC_H |
#ifndef _MALLOC_H |
#ifndef MALLINFO_FIELD_TYPE |
#define MALLINFO_FIELD_TYPE size_t |
#endif /* MALLINFO_FIELD_TYPE */ |
struct mallinfo { |
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ |
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ |
MALLINFO_FIELD_TYPE smblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ |
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ |
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ |
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ |
MALLINFO_FIELD_TYPE fordblks; /* total free space */ |
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ |
}; |
#endif /* _MALLOC_H */ |
#endif /* HAVE_USR_INCLUDE_MALLOC_H */ |
struct mallinfo dlmallinfo(void); |
#endif /* NO_MALLINFO */ |
/* |
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); |
independent_calloc is similar to calloc, but instead of returning a |
single cleared space, it returns an array of pointers to n_elements |
independent elements that can hold contents of size elem_size, each |
of which starts out cleared, and can be independently freed, |
realloc'ed etc. The elements are guaranteed to be adjacently |
allocated (this is not guaranteed to occur with multiple callocs or |
mallocs), which may also improve cache locality in some |
applications. |
The "chunks" argument is optional (i.e., may be null, which is |
probably the most typical usage). If it is null, the returned array |
is itself dynamically allocated and should also be freed when it is |
no longer needed. Otherwise, the chunks array must be of at least |
n_elements in length. It is filled in with the pointers to the |
chunks. |
In either case, independent_calloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and "chunks" |
is null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use regular calloc and assign pointers into this |
space to represent elements. (In this case though, you cannot |
independently free elements.) |
independent_calloc simplifies and speeds up implementations of many |
kinds of pools. It may also be useful when constructing large data |
structures that initially have a fixed number of fixed-sized nodes, |
but the number is not known at compile time, and some of the nodes |
may later need to be freed. For example: |
struct Node { int item; struct Node* next; }; |
struct Node* build_list() { |
struct Node** pool; |
int n = read_number_of_nodes_needed(); |
if (n <= 0) return 0; |
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); |
if (pool == 0) die(); |
// organize into a linked list... |
struct Node* first = pool[0]; |
for (i = 0; i < n-1; ++i) |
pool[i]->next = pool[i+1]; |
free(pool); // Can now free the array (or not, if it is needed later) |
return first; |
} |
*/ |
void** dlindependent_calloc(size_t, size_t, void**); |
/* |
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); |
independent_comalloc allocates, all at once, a set of n_elements |
chunks with sizes indicated in the "sizes" array. It returns |
an array of pointers to these elements, each of which can be |
independently freed, realloc'ed etc. The elements are guaranteed to |
be adjacently allocated (this is not guaranteed to occur with |
multiple callocs or mallocs), which may also improve cache locality |
in some applications. |
The "chunks" argument is optional (i.e., may be null). If it is null |
the returned array is itself dynamically allocated and should also |
be freed when it is no longer needed. Otherwise, the chunks array |
must be of at least n_elements in length. It is filled in with the |
pointers to the chunks. |
In either case, independent_comalloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and chunks is |
null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use a single regular malloc, and assign pointers at |
particular offsets in the aggregate space. (In this case though, you |
cannot independently free elements.) |
independent_comallac differs from independent_calloc in that each |
element may have a different size, and also that it does not |
automatically clear elements. |
independent_comalloc can be used to speed up allocation in cases |
where several structs or objects must always be allocated at the |
same time. For example: |
struct Head { ... } |
struct Foot { ... } |
void send_message(char* msg) { |
int msglen = strlen(msg); |
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; |
void* chunks[3]; |
if (independent_comalloc(3, sizes, chunks) == 0) |
die(); |
struct Head* head = (struct Head*)(chunks[0]); |
char* body = (char*)(chunks[1]); |
struct Foot* foot = (struct Foot*)(chunks[2]); |
// ... |
} |
In general though, independent_comalloc is worth using only for |
larger values of n_elements. For small values, you probably won't |
detect enough difference from series of malloc calls to bother. |
Overuse of independent_comalloc can increase overall memory usage, |
since it cannot reuse existing noncontiguous small chunks that |
might be available for some of the elements. |
*/ |
void** dlindependent_comalloc(size_t, size_t*, void**); |
/* |
pvalloc(size_t n); |
Equivalent to valloc(minimum-page-that-holds(n)), that is, |
round up n to nearest pagesize. |
/** @addtogroup libc |
* @{ |
*/ |
void* dlpvalloc(size_t); |
/** @file |
*/ |
/* |
malloc_trim(size_t pad); |
#ifndef LIBC_MALLOC_H_ |
#define LIBC_MALLOC_H_ |
If possible, gives memory back to the system (via negative arguments |
to sbrk) if there is unused memory at the `high' end of the malloc |
pool or in unused MMAP segments. You can call this after freeing |
large blocks of memory to potentially reduce the system-level memory |
requirements of a program. However, it cannot guarantee to reduce |
memory. Under some allocation patterns, some large free blocks of |
memory will be locked between two used chunks, so they cannot be |
given back to the system. |
#include <sys/types.h> |
The `pad' argument to malloc_trim represents the amount of free |
trailing space to leave untrimmed. If this argument is zero, only |
the minimum amount of memory to maintain internal data structures |
will be left. Non-zero arguments can be supplied to maintain enough |
trailing space to service future expected allocations without having |
to re-obtain memory from the system. |
extern void __heap_init(void); |
extern uintptr_t get_max_heap_addr(void); |
Malloc_trim returns 1 if it actually released any memory, else 0. |
*/ |
int dlmalloc_trim(size_t); |
extern void *malloc(const size_t size); |
extern void *memalign(const size_t align, const size_t size); |
extern void *realloc(const void *addr, const size_t size); |
extern void free(const void *addr); |
/* |
malloc_usable_size(void* p); |
Returns the number of bytes you can actually use in |
an allocated chunk, which may be more than you requested (although |
often not) due to alignment and minimum size constraints. |
You can use this many bytes without worrying about |
overwriting other allocated objects. This is not a particularly great |
programming practice. malloc_usable_size can be more useful in |
debugging and assertions, for example: |
p = malloc(n); |
assert(malloc_usable_size(p) >= 256); |
*/ |
size_t dlmalloc_usable_size(void*); |
/* |
malloc_stats(); |
Prints on stderr the amount of space obtained from the system (both |
via sbrk and mmap), the maximum amount (which may be more than |
current if malloc_trim and/or munmap got called), and the current |
number of bytes allocated via malloc (or realloc, etc) but not yet |
freed. Note that this is the number of bytes allocated, not the |
number requested. It will be larger than the number requested |
because of alignment and bookkeeping overhead. Because it includes |
alignment wastage as being in use, this figure may be greater than |
zero even when no user-level chunks are allocated. |
The reported current and maximum system memory can be inaccurate if |
a program makes other calls to system memory allocation functions |
(normally sbrk) outside of malloc. |
malloc_stats prints only the most commonly interesting statistics. |
More information can be obtained by calling mallinfo. |
*/ |
void dlmalloc_stats(void); |
#endif /* !ONLY_MSPACES */ |
#if MSPACES |
/* |
mspace is an opaque type representing an independent |
region of space that supports mspace_malloc, etc. |
*/ |
typedef void* mspace; |
/* |
create_mspace creates and returns a new independent space with the |
given initial capacity, or, if 0, the default granularity size. It |
returns null if there is no system memory available to create the |
space. If argument locked is non-zero, the space uses a separate |
lock to control access. The capacity of the space will grow |
dynamically as needed to service mspace_malloc requests. You can |
control the sizes of incremental increases of this space by |
compiling with a different DEFAULT_GRANULARITY or dynamically |
setting with mallopt(M_GRANULARITY, value). |
*/ |
mspace create_mspace(size_t capacity, int locked); |
/* |
destroy_mspace destroys the given space, and attempts to return all |
of its memory back to the system, returning the total number of |
bytes freed. After destruction, the results of access to all memory |
used by the space become undefined. |
*/ |
size_t destroy_mspace(mspace msp); |
/* |
create_mspace_with_base uses the memory supplied as the initial base |
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this |
space is used for bookkeeping, so the capacity must be at least this |
large. (Otherwise 0 is returned.) When this initial space is |
exhausted, additional memory will be obtained from the system. |
Destroying this space will deallocate all additionally allocated |
space (if possible) but not the initial base. |
*/ |
mspace create_mspace_with_base(void* base, size_t capacity, int locked); |
/* |
mspace_malloc behaves as malloc, but operates within |
the given space. |
*/ |
void* mspace_malloc(mspace msp, size_t bytes); |
/* |
mspace_free behaves as free, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_free is not actually needed. |
free may be called instead of mspace_free because freed chunks from |
any space are handled by their originating spaces. |
*/ |
void mspace_free(mspace msp, void* mem); |
/* |
mspace_realloc behaves as realloc, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_realloc is not actually |
needed. realloc may be called instead of mspace_realloc because |
realloced chunks from any space are handled by their originating |
spaces. |
*/ |
void* mspace_realloc(mspace msp, void* mem, size_t newsize); |
/* |
mspace_calloc behaves as calloc, but operates within |
the given space. |
*/ |
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); |
/* |
mspace_memalign behaves as memalign, but operates within |
the given space. |
*/ |
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); |
/* |
mspace_independent_calloc behaves as independent_calloc, but |
operates within the given space. |
*/ |
void** mspace_independent_calloc(mspace msp, size_t n_elements, |
size_t elem_size, void* chunks[]); |
/* |
mspace_independent_comalloc behaves as independent_comalloc, but |
operates within the given space. |
*/ |
void** mspace_independent_comalloc(mspace msp, size_t n_elements, |
size_t sizes[], void* chunks[]); |
/* |
mspace_footprint() returns the number of bytes obtained from the |
system for this space. |
*/ |
size_t mspace_footprint(mspace msp); |
#if !NO_MALLINFO |
/* |
mspace_mallinfo behaves as mallinfo, but reports properties of |
the given space. |
*/ |
struct mallinfo mspace_mallinfo(mspace msp); |
#endif /* NO_MALLINFO */ |
/* |
mspace_malloc_stats behaves as malloc_stats, but reports |
properties of the given space. |
*/ |
void mspace_malloc_stats(mspace msp); |
/* |
mspace_trim behaves as malloc_trim, but |
operates within the given space. |
*/ |
int mspace_trim(mspace msp, size_t pad); |
/* |
An alias for mallopt. |
*/ |
int mspace_mallopt(int, int); |
#endif /* MSPACES */ |
#ifdef __cplusplus |
}; /* end of extern "C" */ |
#endif |
#endif /* MALLOC_280_H */ |
/** @} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/devmap.h |
---|
0,0 → 1,59 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_DEVMAP_H_ |
#define LIBC_DEVMAP_H_ |
#include <ipc/devmap.h> |
#include <async.h> |
extern int devmap_get_phone(devmap_interface_t, unsigned int); |
extern void devmap_hangup_phone(devmap_interface_t iface); |
extern int devmap_driver_register(const char *, async_client_conn_t); |
extern int devmap_device_register(const char *, dev_handle_t *); |
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int); |
extern int devmap_device_connect(dev_handle_t, unsigned int); |
extern int devmap_null_create(void); |
extern void devmap_null_destroy(int); |
extern ipcarg_t devmap_device_get_count(void); |
extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/sys/stat.h |
---|
36,7 → 36,26 |
#define LIBC_SYS_STAT_H_ |
#include <sys/types.h> |
#include <bool.h> |
#include <ipc/vfs.h> |
#include <ipc/devmap.h> |
struct stat { |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
fs_index_t index; |
unsigned lnkcnt; |
bool is_file; |
off_t size; |
union { |
struct { |
dev_handle_t device; |
} devfs_stat; |
}; |
}; |
extern int fstat(int, struct stat *); |
extern int stat(const char *, struct stat *); |
extern int mkdir(const char *, mode_t); |
#endif |
/branches/arm/uspace/lib/libc/include/sys/types.h |
---|
37,11 → 37,15 |
#include <libarch/types.h> |
typedef unsigned long size_t; |
typedef signed long ssize_t; |
typedef long off_t; |
typedef int mode_t; |
typedef int32_t wchar_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/byteorder.h |
---|
35,33 → 35,48 |
#ifndef LIBC_BYTEORDER_H_ |
#define LIBC_BYTEORDER_H_ |
#include <libarch/byteorder.h> |
#include <stdint.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
#if !(defined(__BE__) ^ defined(__LE__)) |
#error The architecture must be either big-endian or little-endian. |
#endif |
#ifdef ARCH_IS_BIG_ENDIAN |
#ifdef __BE__ |
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_le2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_le2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_le2host(n) (uint64_t_byteorder_swap(n)) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_le(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_le(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_be2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_be2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_be2host(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_be(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_be(n) (uint64_t_byteorder_swap(n)) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
/branches/arm/uspace/lib/libc/include/string.h |
---|
35,32 → 35,59 |
#ifndef LIBC_STRING_H_ |
#define LIBC_STRING_H_ |
#include <mem.h> |
#include <sys/types.h> |
#include <bool.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
#define U_SPECIAL '?' |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
/** No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
extern int bcmp(const char *, const char *, size_t); |
/** Maximum size of a string containing @c length characters */ |
#define STR_BOUNDS(length) ((length) << 2) |
extern int strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz); |
extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz); |
extern char *strcpy(char *, const char *); |
extern char *strncpy(char *, const char *, size_t); |
extern size_t str_size(const char *str); |
extern size_t wstr_size(const wchar_t *str); |
extern char *strcat(char *, const char *); |
extern size_t str_lsize(const char *str, size_t max_len); |
extern size_t wstr_lsize(const wchar_t *str, size_t max_len); |
extern size_t strlen(const char *); |
extern size_t str_length(const char *str); |
extern size_t wstr_length(const wchar_t *wstr); |
extern char *strdup(const char *); |
extern size_t str_nlength(const char *str, size_t size); |
extern size_t wstr_nlength(const wchar_t *str, size_t size); |
extern char *strchr(const char *, int); |
extern char *strrchr(const char *, int); |
extern bool ascii_check(wchar_t ch); |
extern bool chr_check(wchar_t ch); |
extern int str_cmp(const char *s1, const char *s2); |
extern int str_lcmp(const char *s1, const char *s2, size_t max_len); |
extern void str_cpy(char *dest, size_t size, const char *src); |
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n); |
extern void str_append(char *dest, size_t size, const char *src); |
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); |
extern const char *str_chr(const char *str, wchar_t ch); |
extern const char *str_rchr(const char *str, wchar_t ch); |
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); |
extern bool wstr_remove(wchar_t *str, size_t pos); |
extern char *str_dup(const char *); |
/* |
* TODO: Get rid of this. |
*/ |
extern int stricmp(const char *, const char *); |
extern long int strtol(const char *, char **, int); |
extern unsigned long strtoul(const char *, char **, int); |
/branches/arm/uspace/lib/libc/include/fibril_sync.h |
---|
0,0 → 1,104 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_FIBRIL_SYNC_H_ |
#define LIBC_FIBRIL_SYNC_H_ |
#include <async.h> |
#include <fibril.h> |
#include <adt/list.h> |
#include <libarch/tls.h> |
typedef struct { |
int counter; |
link_t waiters; |
} fibril_mutex_t; |
#define FIBRIL_MUTEX_INITIALIZE(name) \ |
fibril_mutex_t name = { \ |
.counter = 1, \ |
.waiters = { \ |
.prev = &name.waiters, \ |
.next = &name.waiters, \ |
} \ |
} |
typedef struct { |
unsigned writers; |
unsigned readers; |
link_t waiters; |
} fibril_rwlock_t; |
#define FIBRIL_RWLOCK_INITIALIZE(name) \ |
fibril_rwlock_t name = { \ |
.readers = 0, \ |
.writers = 0, \ |
.waiters = { \ |
.prev = &name.waiters, \ |
.next = &name.waiters, \ |
} \ |
} |
typedef struct { |
link_t waiters; |
} fibril_condvar_t; |
#define FIBRIL_CONDVAR_INITIALIZE(name) \ |
fibril_condvar_t name = { \ |
.waiters = { \ |
.next = &name.waiters, \ |
.prev = &name.waiters, \ |
} \ |
} |
extern void fibril_mutex_initialize(fibril_mutex_t *); |
extern void fibril_mutex_lock(fibril_mutex_t *); |
extern bool fibril_mutex_trylock(fibril_mutex_t *); |
extern void fibril_mutex_unlock(fibril_mutex_t *); |
extern void fibril_rwlock_initialize(fibril_rwlock_t *); |
extern void fibril_rwlock_read_lock(fibril_rwlock_t *); |
extern void fibril_rwlock_write_lock(fibril_rwlock_t *); |
extern void fibril_rwlock_read_unlock(fibril_rwlock_t *); |
extern void fibril_rwlock_write_unlock(fibril_rwlock_t *); |
extern void fibril_condvar_initialize(fibril_condvar_t *); |
extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *); |
extern void fibril_condvar_signal(fibril_condvar_t *); |
extern void fibril_condvar_broadcast(fibril_condvar_t *); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/loader/pcb.h |
---|
37,6 → 37,7 |
#define LIBC_PCB_H_ |
#include <sys/types.h> |
#include <vfs/vfs.h> |
typedef void (*entry_point_t)(void); |
45,27 → 46,34 |
* Holds pointers to data passed from the program loader to the program |
* and/or to the dynamic linker. This includes the program entry point, |
* arguments, environment variables etc. |
* |
*/ |
typedef struct { |
/** Program entry point */ |
/** Program entry point. */ |
entry_point_t entry; |
/** Number of command-line arguments */ |
/** Number of command-line arguments. */ |
int argc; |
/** Command-line arguments */ |
/** Command-line arguments. */ |
char **argv; |
/** Number of preset files. */ |
int filc; |
/** Preset files. */ |
fdi_node_t **filv; |
/* |
* ELF-specific data |
* ELF-specific data. |
*/ |
/** Pointer to ELF dynamic section of the program */ |
/** Pointer to ELF dynamic section of the program. */ |
void *dynamic; |
/** Pointer to dynamic section of the runtime linker */ |
void *rtld_dynamic; |
/** Runtime-linker load bias */ |
uintptr_t rtld_bias; |
} pcb_t; |
/** |
* A pointer to the program control block. Having received the PCB pointer, |
* the C library startup code stores it here for later use. |
*/ |
extern pcb_t *__pcb; |
#endif |
/branches/arm/uspace/lib/libc/include/loader/loader.h |
---|
37,6 → 37,7 |
#define LIBC_LOADER_H_ |
#include <task.h> |
#include <vfs/vfs.h> |
/** Abstraction of a loader connection */ |
typedef struct { |
44,10 → 45,12 |
int phone_id; |
} loader_t; |
extern loader_t *loader_spawn(void); |
extern int loader_spawn(const char *); |
extern loader_t *loader_connect(void); |
extern int loader_get_task_id(loader_t *, task_id_t *); |
extern int loader_set_pathname(loader_t *, const char *); |
extern int loader_set_args(loader_t *, char *const []); |
extern int loader_set_args(loader_t *, char *const[]); |
extern int loader_set_files(loader_t *, fdi_node_t *const[]); |
extern int loader_load_program(loader_t *); |
extern int loader_run(loader_t *); |
extern void loader_abort(loader_t *); |
/branches/arm/uspace/lib/libc/include/fcntl.h |
---|
35,13 → 35,13 |
#ifndef LIBC_FCNTL_H_ |
#define LIBC_FCNTL_H_ |
#define O_CREAT 1 |
#define O_EXCL 2 |
#define O_TRUNC 4 |
#define O_APPEND 8 |
#define O_RDONLY 16 |
#define O_RDWR 32 |
#define O_WRONLY 64 |
#define O_CREAT 1 |
#define O_EXCL 2 |
#define O_TRUNC 4 |
#define O_APPEND 8 |
#define O_RDONLY 16 |
#define O_RDWR 32 |
#define O_WRONLY 64 |
extern int open(const char *, int, ...); |
/branches/arm/uspace/lib/libc/include/dirent.h |
---|
35,7 → 35,7 |
#ifndef LIBC_DIRENT_H_ |
#define LIBC_DIRENT_H_ |
#define NAME_MAX 256 |
#define NAME_MAX 256 |
struct dirent { |
char d_name[NAME_MAX + 1]; |
46,7 → 46,6 |
struct dirent res; |
} DIR; |
extern DIR *opendir(const char *); |
extern struct dirent *readdir(DIR *); |
extern void rewinddir(DIR *); |
/branches/arm/uspace/lib/libc/include/thread.h |
---|
45,7 → 45,7 |
extern void __thread_main(uspace_arg_t *); |
extern int thread_create(void (*)(void *), void *, char *, thread_id_t *); |
extern void thread_exit(int); |
extern void thread_exit(int) __attribute__ ((noreturn)); |
extern void thread_detach(thread_id_t); |
extern int thread_join(thread_id_t); |
extern thread_id_t thread_get_id(void); |
/branches/arm/uspace/lib/libc/include/event.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_EVENT_H_ |
#define LIBC_EVENT_H_ |
#include <kernel/ipc/event_types.h> |
#include <ipc/ipc.h> |
extern int event_subscribe(event_type_t, ipcarg_t); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/include/ddi.h |
---|
37,9 → 37,11 |
#include <task.h> |
extern int physmem_map(void *pf, void *vp, unsigned long pages, int flags); |
extern int iospace_enable(task_id_t id, void *ioaddr, unsigned long size); |
extern int preemption_control(int enable); |
extern int device_assign_devno(void); |
extern int physmem_map(void *, void *, unsigned long, int); |
extern int iospace_enable(task_id_t, void *, unsigned long); |
extern int preemption_control(int); |
extern int pio_enable(void *, size_t, void **); |
#endif |
/branches/arm/uspace/lib/libc/include/libc.h |
---|
39,14 → 39,20 |
#include <kernel/syscall/syscall.h> |
#include <libarch/syscall.h> |
#define __SYSCALL0(id) __syscall(0, 0, 0, 0, 0, 0, id) |
#define __SYSCALL1(id, p1) __syscall(p1, 0, 0, 0, 0, 0, id) |
#define __SYSCALL2(id, p1, p2) __syscall(p1, p2, 0, 0, 0, 0, id) |
#define __SYSCALL3(id, p1, p2, p3) __syscall(p1, p2, p3, 0, 0, 0, id) |
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall(p1, p2, p3, p4, 0, 0, id) |
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall(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) \ |
__syscall(p1, p2, p3, p4, p5, p6,id) |
__syscall6(p1, p2, p3, p4, p5, p6, id) |
extern void __main(void *pcb_ptr); |
extern void __exit(void); |
/branches/arm/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/arm/uspace/lib/libc/include/align.h |
---|
35,21 → 35,28 |
#ifndef LIBC_ALIGN_H_ |
#define LIBC_ALIGN_H_ |
/** Align to the nearest lower address. |
/** Align to the nearest lower address which is a power of two. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1)) |
/** Align to the nearest higher address. |
/** Align to the nearest higher address which is a power of two. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(s, a) ((long)((s) + ((a) - 1)) & ~((long) (a) - 1)) |
/** Round up to the nearest higher boundary. |
* |
* @param n Number to be aligned. |
* @param b Boundary, arbitrary unsigned number. |
*/ |
#define ROUND_UP(n, b) (((n) / (b) + ((n) % (b) != 0)) * (b)) |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/include/syscall.h |
---|
32,15 → 32,28 |
/** |
* @file |
* @brief Syscall function declaration for architectures that don't |
* inline syscalls. |
* inline syscalls or architectures that handle syscalls |
* according to the number of arguments. |
*/ |
#ifndef LIBC_SYSCALL_H_ |
#define LIBC_SYSCALL_H_ |
#ifndef LIBARCH_SYSCALL_GENERIC |
#error "You can't include this file directly." |
#endif |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall |
#define __syscall1 __syscall |
#define __syscall2 __syscall |
#define __syscall3 __syscall |
#define __syscall4 __syscall |
#define __syscall5 __syscall |
#define __syscall6 __syscall |
extern sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2, |
const sysarg_t p3, const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, |
const syscall_t id); |
/branches/arm/uspace/lib/libc/generic/libadt/hash_table.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/generic/libadt/list.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/generic/io/sprintf.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/generic/io/vsprintf.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/generic/io/stream.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/generic/io/console.c |
---|
0,0 → 1,113 |
/* |
* Copyright (c) 2006 Josef Cejka |
* Copyright (c) 2006 Jakub Vana |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <async.h> |
#include <io/console.h> |
#include <ipc/console.h> |
void console_clear(int phone) |
{ |
async_msg_0(phone, CONSOLE_CLEAR); |
} |
int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols) |
{ |
return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols); |
} |
void console_set_style(int phone, int style) |
{ |
async_msg_1(phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int phone, int fg_color, int bg_color, int flags) |
{ |
async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int phone, int fg_color, int bg_color) |
{ |
async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int phone, bool show) |
{ |
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false); |
} |
int console_get_color_cap(int phone, int *ccap) |
{ |
ipcarg_t ccap_tmp; |
int rc; |
rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp); |
*ccap = ccap_tmp; |
return rc; |
} |
void console_kcon_enable(int phone) |
{ |
async_msg_0(phone, CONSOLE_KCON_ENABLE); |
} |
void console_goto(int phone, ipcarg_t row, ipcarg_t col) |
{ |
async_msg_2(phone, CONSOLE_GOTO, row, col); |
} |
bool console_get_event(int phone, console_event_t *event) |
{ |
ipcarg_t type; |
ipcarg_t key; |
ipcarg_t mods; |
ipcarg_t c; |
int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c); |
if (rc < 0) |
return false; |
event->type = type; |
event->key = key; |
event->mods = mods; |
event->c = c; |
return true; |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/io/io.c |
---|
30,78 → 30,564 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <libc.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdio.h> |
#include <io/io.h> |
#include <fcntl.h> |
#include <assert.h> |
#include <string.h> |
#include <errno.h> |
#include <bool.h> |
#include <malloc.h> |
#include <io/klog.h> |
#include <vfs/vfs.h> |
#include <ipc/devmap.h> |
#include <adt/list.h> |
const static char nl = '\n'; |
static void _fflushbuf(FILE *stream); |
int puts(const char *str) |
static FILE stdin_null = { |
.fd = -1, |
.error = true, |
.eof = true, |
.klog = false, |
.phone = -1, |
.btype = _IONBF, |
.buf = NULL, |
.buf_size = 0, |
.buf_head = NULL |
}; |
static FILE stdout_klog = { |
.fd = -1, |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1, |
.btype = _IOLBF, |
.buf = NULL, |
.buf_size = BUFSIZ, |
.buf_head = NULL |
}; |
static FILE stderr_klog = { |
.fd = -1, |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1, |
.btype = _IONBF, |
.buf = NULL, |
.buf_size = 0, |
.buf_head = NULL |
}; |
FILE *stdin = NULL; |
FILE *stdout = NULL; |
FILE *stderr = NULL; |
static LIST_INITIALIZE(files); |
void __stdio_init(int filc, fdi_node_t *filv[]) |
{ |
size_t count; |
if (filc > 0) { |
stdin = fopen_node(filv[0], "r"); |
} else { |
stdin = &stdin_null; |
list_append(&stdin->link, &files); |
} |
if (str == NULL) |
return putnchars("(NULL)", 6); |
if (filc > 1) { |
stdout = fopen_node(filv[1], "w"); |
} else { |
stdout = &stdout_klog; |
list_append(&stdout->link, &files); |
} |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) { |
if (write_stdout(&nl, 1) == 1) |
return 0; |
if (filc > 2) { |
stderr = fopen_node(filv[2], "w"); |
} else { |
stderr = &stderr_klog; |
list_append(&stderr->link, &files); |
} |
} |
void __stdio_done(void) |
{ |
link_t *link = files.next; |
return EOF; |
while (link != &files) { |
FILE *file = list_get_instance(link, FILE, link); |
fclose(file); |
link = files.next; |
} |
} |
/** Put count chars from buffer to stdout without adding newline |
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed! |
* @param count |
* @return 0 on succes, EOF on fail |
static bool parse_mode(const char *mode, int *flags) |
{ |
/* Parse mode except first character. */ |
const char *mp = mode; |
if (*mp++ == 0) { |
errno = EINVAL; |
return false; |
} |
if ((*mp == 'b') || (*mp == 't')) |
mp++; |
bool plus; |
if (*mp == '+') { |
mp++; |
plus = true; |
} else |
plus = false; |
if (*mp != 0) { |
errno = EINVAL; |
return false; |
} |
/* Parse first character of mode and determine flags for open(). */ |
switch (mode[0]) { |
case 'r': |
*flags = plus ? O_RDWR : O_RDONLY; |
break; |
case 'w': |
*flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
break; |
case 'a': |
/* TODO: a+ must read from beginning, append to the end. */ |
if (plus) { |
errno = ENOTSUP; |
return false; |
} |
*flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
default: |
errno = EINVAL; |
return false; |
} |
return true; |
} |
/** Set stream buffer. */ |
void setvbuf(FILE *stream, void *buf, int mode, size_t size) |
{ |
stream->btype = mode; |
stream->buf = buf; |
stream->buf_size = size; |
stream->buf_head = stream->buf; |
} |
static void _setvbuf(FILE *stream) |
{ |
/* FIXME: Use more complex rules for setting buffering options. */ |
switch (stream->fd) { |
case 1: |
setvbuf(stream, NULL, _IOLBF, BUFSIZ); |
break; |
case 0: |
case 2: |
setvbuf(stream, NULL, _IONBF, 0); |
break; |
default: |
setvbuf(stream, NULL, _IOFBF, BUFSIZ); |
} |
} |
/** Allocate stream buffer. */ |
static int _fallocbuf(FILE *stream) |
{ |
assert(stream->buf == NULL); |
stream->buf = malloc(stream->buf_size); |
if (stream->buf == NULL) { |
errno = ENOMEM; |
return -1; |
} |
stream->buf_head = stream->buf; |
return 0; |
} |
/** Open a stream. |
* |
* @param path Path of the file to open. |
* @param mode Mode string, (r|w|a)[b|t][+]. |
* |
*/ |
int putnchars(const char *buf, size_t count) |
FILE *fopen(const char *path, const char *mode) |
{ |
if (write_stdout((void *) buf, count) == count) |
return 0; |
int flags; |
if (!parse_mode(mode, &flags)) |
return NULL; |
return EOF; |
/* Open file. */ |
FILE *stream = malloc(sizeof(FILE)); |
if (stream == NULL) { |
errno = ENOMEM; |
return NULL; |
} |
stream->fd = open(path, flags, 0666); |
if (stream->fd < 0) { |
/* errno was set by open() */ |
free(stream); |
return NULL; |
} |
stream->error = false; |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
return stream; |
} |
/** Same as puts, but does not print newline at end |
FILE *fdopen(int fd, const char *mode) |
{ |
/* Open file. */ |
FILE *stream = malloc(sizeof(FILE)); |
if (stream == NULL) { |
errno = ENOMEM; |
return NULL; |
} |
stream->fd = fd; |
stream->error = false; |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
return stream; |
} |
FILE *fopen_node(fdi_node_t *node, const char *mode) |
{ |
int flags; |
if (!parse_mode(mode, &flags)) |
return NULL; |
/* Open file. */ |
FILE *stream = malloc(sizeof(FILE)); |
if (stream == NULL) { |
errno = ENOMEM; |
return NULL; |
} |
stream->fd = open_node(node, flags); |
if (stream->fd < 0) { |
/* errno was set by open_node() */ |
free(stream); |
return NULL; |
} |
stream->error = false; |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
return stream; |
} |
int fclose(FILE *stream) |
{ |
int rc = 0; |
fflush(stream); |
if (stream->phone >= 0) |
ipc_hangup(stream->phone); |
if (stream->fd >= 0) |
rc = close(stream->fd); |
list_remove(&stream->link); |
if ((stream != &stdin_null) |
&& (stream != &stdout_klog) |
&& (stream != &stderr_klog)) |
free(stream); |
stream = NULL; |
if (rc != 0) { |
/* errno was set by close() */ |
return EOF; |
} |
return 0; |
} |
/** Read from a stream. |
* |
* @param buf Destination buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to read. |
* @param stream Pointer to the stream. |
* |
*/ |
int putstr(const char *str) |
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream) |
{ |
size_t count; |
size_t left = size * nmemb; |
size_t done = 0; |
if (str == NULL) |
return putnchars("(NULL)", 6); |
/* Make sure no data is pending write. */ |
_fflushbuf(stream); |
while ((left > 0) && (!stream->error) && (!stream->eof)) { |
ssize_t rd = read(stream->fd, buf + done, left); |
if (rd < 0) |
stream->error = true; |
else if (rd == 0) |
stream->eof = true; |
else { |
left -= rd; |
done += rd; |
} |
} |
return (done / size); |
} |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) |
return 0; |
static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) |
{ |
size_t left = size * nmemb; |
size_t done = 0; |
return EOF; |
while ((left > 0) && (!stream->error)) { |
ssize_t wr; |
if (stream->klog) |
wr = klog_write(buf + done, left); |
else |
wr = write(stream->fd, buf + done, left); |
if (wr <= 0) |
stream->error = true; |
else { |
left -= wr; |
done += wr; |
} |
} |
return (done / size); |
} |
int putchar(int c) |
/** Drain stream buffer, do not sync stream. */ |
static void _fflushbuf(FILE *stream) |
{ |
unsigned char ch = c; |
if (write_stdout((void *) &ch, 1) == 1) |
return c; |
size_t bytes_used; |
if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) |
return; |
bytes_used = stream->buf_head - stream->buf; |
if (bytes_used == 0) |
return; |
(void) _fwrite(stream->buf, 1, bytes_used, stream); |
stream->buf_head = stream->buf; |
} |
/** Write to a stream. |
* |
* @param buf Source buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to write. |
* @param stream Pointer to the stream. |
* |
*/ |
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) |
{ |
uint8_t *data; |
size_t bytes_left; |
size_t now; |
size_t buf_free; |
size_t total_written; |
size_t i; |
uint8_t b; |
bool need_flush; |
/* If not buffered stream, write out directly. */ |
if (stream->btype == _IONBF) { |
now = _fwrite(buf, size, nmemb, stream); |
fflush(stream); |
return now; |
} |
/* Perform lazy allocation of stream buffer. */ |
if (stream->buf == NULL) { |
if (_fallocbuf(stream) != 0) |
return 0; /* Errno set by _fallocbuf(). */ |
} |
data = (uint8_t *) buf; |
bytes_left = size * nmemb; |
total_written = 0; |
need_flush = false; |
while ((!stream->error) && (bytes_left > 0)) { |
buf_free = stream->buf_size - (stream->buf_head - stream->buf); |
if (bytes_left > buf_free) |
now = buf_free; |
else |
now = bytes_left; |
for (i = 0; i < now; i++) { |
b = data[i]; |
stream->buf_head[i] = b; |
if ((b == '\n') && (stream->btype == _IOLBF)) |
need_flush = true; |
} |
buf += now; |
stream->buf_head += now; |
buf_free -= now; |
bytes_left -= now; |
total_written += now; |
if (buf_free == 0) { |
/* Only need to drain buffer. */ |
_fflushbuf(stream); |
need_flush = false; |
} |
} |
if (need_flush) |
fflush(stream); |
return (total_written / size); |
} |
int fputc(wchar_t c, FILE *stream) |
{ |
char buf[STR_BOUNDS(1)]; |
size_t sz = 0; |
if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) { |
size_t wr = fwrite(buf, sz, 1, stream); |
if (wr < sz) |
return EOF; |
return (int) c; |
} |
return EOF; |
} |
int putchar(wchar_t c) |
{ |
return fputc(c, stdout); |
} |
int fputs(const char *str, FILE *stream) |
{ |
return fwrite(str, str_size(str), 1, stream); |
} |
int puts(const char *str) |
{ |
return fputs(str, stdout); |
} |
int fgetc(FILE *stream) |
{ |
char c; |
/* This could be made faster by only flushing when needed. */ |
if (stdout) |
fflush(stdout); |
if (stderr) |
fflush(stderr); |
if (fread(&c, sizeof(char), 1, stream) < sizeof(char)) |
return EOF; |
return (int) c; |
} |
int getchar(void) |
{ |
unsigned char c; |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
return fgetc(stdin); |
} |
int fseek(FILE *stream, long offset, int origin) |
{ |
off_t rc = lseek(stream->fd, offset, origin); |
if (rc == (off_t) (-1)) { |
/* errno has been set by lseek. */ |
return -1; |
} |
return EOF; |
stream->eof = false; |
return 0; |
} |
void rewind(FILE *stream) |
{ |
(void) fseek(stream, 0, SEEK_SET); |
} |
int fflush(FILE *stream) |
{ |
_fflushbuf(stream); |
if (stream->klog) { |
klog_update(); |
return EOK; |
} |
if (stream->fd >= 0) |
return fsync(stream->fd); |
return ENOENT; |
} |
int feof(FILE *stream) |
{ |
return stream->eof; |
} |
int ferror(FILE *stream) |
{ |
return stream->error; |
} |
int fphone(FILE *stream) |
{ |
if (stream->fd >= 0) { |
if (stream->phone < 0) |
stream->phone = fd_phone(stream->fd); |
return stream->phone; |
} |
return -1; |
} |
int fnode(FILE *stream, fdi_node_t *node) |
{ |
if (stream->fd >= 0) |
return fd_node(stream->fd, node); |
return ENOENT; |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/io/printf_core.c |
---|
1,6 → 1,7 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2006 Josef Cejka |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
27,12 → 28,12 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Printing functions. |
* @brief Printing functions. |
*/ |
#include <unistd.h> |
41,20 → 42,30 |
#include <ctype.h> |
#include <string.h> |
#define __PRINTF_FLAG_PREFIX 0x00000001 /**< show prefixes 0x or 0*/ |
#define __PRINTF_FLAG_SIGNED 0x00000002 /**< signed / unsigned number */ |
#define __PRINTF_FLAG_ZEROPADDED 0x00000004 /**< print leading zeroes */ |
#define __PRINTF_FLAG_LEFTALIGNED 0x00000010 /**< align to left */ |
#define __PRINTF_FLAG_SHOWPLUS 0x00000020 /**< always show + sign */ |
#define __PRINTF_FLAG_SPACESIGN 0x00000040 /**< print space instead of plus */ |
#define __PRINTF_FLAG_BIGCHARS 0x00000080 /**< show big characters */ |
#define __PRINTF_FLAG_NEGATIVE 0x00000100 /**< number has - sign */ |
/** show prefixes 0x or 0 */ |
#define __PRINTF_FLAG_PREFIX 0x00000001 |
/** signed / unsigned number */ |
#define __PRINTF_FLAG_SIGNED 0x00000002 |
/** print leading zeroes */ |
#define __PRINTF_FLAG_ZEROPADDED 0x00000004 |
/** align to left */ |
#define __PRINTF_FLAG_LEFTALIGNED 0x00000010 |
/** always show + sign */ |
#define __PRINTF_FLAG_SHOWPLUS 0x00000020 |
/** print space instead of plus */ |
#define __PRINTF_FLAG_SPACESIGN 0x00000040 |
/** show big characters */ |
#define __PRINTF_FLAG_BIGCHARS 0x00000080 |
/** number has - sign */ |
#define __PRINTF_FLAG_NEGATIVE 0x00000100 |
#define PRINT_NUMBER_BUFFER_SIZE (64+5) /**< Buffer big enought for 64 bit number |
* printed in base 2, sign, prefix and |
* 0 to terminate string.. (last one is only for better testing |
* end of buffer by zero-filling subroutine) |
*/ |
/** |
* Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0 |
* to terminate string... (last one is only for better testing end of buffer by |
* zero-filling subroutine) |
*/ |
#define PRINT_NUMBER_BUFFER_SIZE (64 + 5) |
/** Enumeration of possible arguments types. |
*/ |
typedef enum { |
63,171 → 74,296 |
PrintfQualifierInt, |
PrintfQualifierLong, |
PrintfQualifierLongLong, |
PrintfQualifierSizeT, |
PrintfQualifierPointer |
} qualifier_t; |
static char digits_small[] = "0123456789abcdef"; /**< Small hexadecimal characters */ |
static char digits_big[] = "0123456789ABCDEF"; /**< Big hexadecimal characters */ |
static char nullstr[] = "(NULL)"; |
static char digits_small[] = "0123456789abcdef"; |
static char digits_big[] = "0123456789ABCDEF"; |
static char invalch = U_SPECIAL; |
/** Print count chars from buffer without adding newline |
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed! |
* @param count |
* @param ps output method and its data |
* @return number of printed characters |
/** Print one or more characters without adding newline. |
* |
* @param buf Buffer holding characters with size of |
* at least size bytes. NULL is not allowed! |
* @param size Size of the buffer in bytes. |
* @param ps Output method and its data. |
* |
* @return Number of characters printed. |
* |
*/ |
static int printf_putnchars(const char * buf, size_t count, |
struct printf_spec *ps) |
static int printf_putnchars(const char *buf, size_t size, |
printf_spec_t *ps) |
{ |
return ps->write((void *)buf, count, ps->data); |
return ps->str_write((void *) buf, size, ps->data); |
} |
/** Print string without added newline |
* @param str string to print |
* @param ps write function specification and support data |
* @return number of printed characters |
/** Print one or more wide characters without adding newline. |
* |
* @param buf Buffer holding wide characters with size of |
* at least size bytes. NULL is not allowed! |
* @param size Size of the buffer in bytes. |
* @param ps Output method and its data. |
* |
* @return Number of wide characters printed. |
* |
*/ |
static int printf_putstr(const char * str, struct printf_spec *ps) |
static int printf_wputnchars(const wchar_t *buf, size_t size, |
printf_spec_t *ps) |
{ |
size_t count; |
return ps->wstr_write((void *) buf, size, ps->data); |
} |
/** Print string without adding a newline. |
* |
* @param str String to print. |
* @param ps Write function specification and support data. |
* |
* @return Number of characters printed. |
* |
*/ |
static int printf_putstr(const char *str, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putnchars(nullstr, str_size(nullstr), ps); |
if (str == NULL) |
return printf_putnchars("(NULL)", 6, ps); |
return ps->str_write((void *) str, str_size(str), ps->data); |
} |
count = strlen(str); |
return ps->write((void *) str, count, ps->data); |
/** Print one ASCII character. |
* |
* @param c ASCII character to be printed. |
* @param ps Output method. |
* |
* @return Number of characters printed. |
* |
*/ |
static int printf_putchar(const char ch, printf_spec_t *ps) |
{ |
if (!ascii_check(ch)) |
return ps->str_write((void *) &invalch, 1, ps->data); |
return ps->str_write(&ch, 1, ps->data); |
} |
/** Print one character to output |
* @param c one character |
* @param ps output method |
* @return number of printed characters |
/** Print one wide character. |
* |
* @param c Wide character to be printed. |
* @param ps Output method. |
* |
* @return Number of characters printed. |
* |
*/ |
static int printf_putchar(int c, struct printf_spec *ps) |
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps) |
{ |
unsigned char ch = c; |
if (!chr_check(ch)) |
return ps->str_write((void *) &invalch, 1, ps->data); |
return ps->write((void *) &ch, 1, ps->data); |
return ps->wstr_write(&ch, sizeof(wchar_t), ps->data); |
} |
/** Print one formatted character |
* @param c character to print |
* @param width |
* @param flags |
* @return number of printed characters |
/** Print one formatted ASCII character. |
* |
* @param ch Character to print. |
* @param width Width modifier. |
* @param flags Flags that change the way the character is printed. |
* |
* @return Number of characters printed, negative value on failure. |
* |
*/ |
static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps) |
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps) |
{ |
int counter = 0; |
size_t counter = 0; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
/* |
* One space is consumed by the character itself, hence the |
* predecrement. |
*/ |
while (--width > 0) { |
if (printf_putchar(' ', ps) > 0) |
++counter; |
/* |
* One space is consumed by the character itself, hence |
* the predecrement. |
*/ |
if (printf_putchar(' ', ps) > 0) |
counter++; |
} |
} |
if (printf_putchar(c, ps) > 0) |
if (printf_putchar(ch, ps) > 0) |
counter++; |
/* |
* One space is consumed by the character itself, hence the |
* predecrement. |
*/ |
while (--width > 0) { |
/* |
* One space is consumed by the character itself, hence |
* the predecrement. |
*/ |
if (printf_putchar(' ', ps) > 0) |
++counter; |
counter++; |
} |
return ++counter; |
return (int) (counter + 1); |
} |
/** Print one string |
* @param s string |
* @param width |
* @param precision |
* @param flags |
* @return number of printed characters |
/** Print one formatted wide character. |
* |
* @param ch Character to print. |
* @param width Width modifier. |
* @param flags Flags that change the way the character is printed. |
* |
* @return Number of characters printed, negative value on failure. |
* |
*/ |
static int print_string(char *s, int width, int precision, uint64_t flags, |
struct printf_spec *ps) |
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps) |
{ |
int counter = 0; |
size_t size; |
int retval; |
if (s == NULL) { |
return printf_putstr("(NULL)", ps); |
size_t counter = 0; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
while (--width > 0) { |
/* |
* One space is consumed by the character itself, hence |
* the predecrement. |
*/ |
if (printf_putchar(' ', ps) > 0) |
counter++; |
} |
} |
size = strlen(s); |
if (printf_putwchar(ch, ps) > 0) |
counter++; |
while (--width > 0) { |
/* |
* One space is consumed by the character itself, hence |
* the predecrement. |
*/ |
if (printf_putchar(' ', ps) > 0) |
counter++; |
} |
return (int) (counter + 1); |
} |
/* print leading spaces */ |
/** Print string. |
* |
* @param str String to be printed. |
* @param width Width modifier. |
* @param precision Precision modifier. |
* @param flags Flags that modify the way the string is printed. |
* |
* @return Number of characters printed, negative value on failure. |
*/ |
static int print_str(char *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
if (precision == 0) |
precision = size; |
/* Print leading spaces. */ |
size_t strw = str_length(str); |
if (precision == 0) |
precision = strw; |
/* Left padding */ |
size_t counter = 0; |
width -= precision; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
} |
if ((retval = printf_putnchars(s, size < precision ? size : precision, |
ps)) < 0) { |
/* Part of @a str fitting into the alloted space. */ |
int retval; |
size_t size = str_lsize(str, precision); |
if ((retval = printf_putnchars(str, size, ps)) < 0) |
return -counter; |
counter += retval; |
/* Right padding */ |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
counter += retval; |
return ((int) counter); |
} |
/** Print wide string. |
* |
* @param str Wide string to be printed. |
* @param width Width modifier. |
* @param precision Precision modifier. |
* @param flags Flags that modify the way the string is printed. |
* |
* @return Number of wide characters printed, negative value on failure. |
*/ |
static int print_wstr(wchar_t *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
/* Print leading spaces. */ |
size_t strw = wstr_length(str); |
if (precision == 0) |
precision = strw; |
/* Left padding */ |
size_t counter = 0; |
width -= precision; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
} |
/* Part of @a wstr fitting into the alloted space. */ |
int retval; |
size_t size = wstr_lsize(str, precision); |
if ((retval = printf_wputnchars(str, size, ps)) < 0) |
return -counter; |
counter += retval; |
/* Right padding */ |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
++counter; |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
return counter; |
return ((int) counter); |
} |
/** Print number in given base |
/** Print a number in a given base. |
* |
* Print significant digits of a number in given |
* base. |
* Print significant digits of a number in given base. |
* |
* @param num Number to print. |
* @param width |
* @param precision |
* @param base Base to print the number in (should |
* be in range 2 .. 16). |
* @param flags output modifiers |
* @return number of printed characters |
* @param num Number to print. |
* @param width Width modifier. |
* @param precision Precision modifier. |
* @param base Base to print the number in (must be between 2 and 16). |
* @param flags Flags that modify the way the number is printed. |
* |
* @return Number of characters printed. |
* |
*/ |
static int print_number(uint64_t num, int width, int precision, int base, |
uint64_t flags, struct printf_spec *ps) |
uint32_t flags, printf_spec_t *ps) |
{ |
char *digits = digits_small; |
char d[PRINT_NUMBER_BUFFER_SIZE]; /* this is good enough even for |
* base == 2, prefix and sign */ |
char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1]; |
int size = 0; /* size of number with all prefixes and signs */ |
int number_size; /* size of plain number */ |
char sgn; |
int retval; |
int counter = 0; |
char *digits; |
if (flags & __PRINTF_FLAG_BIGCHARS) |
digits = digits_big; |
else |
digits = digits_small; |
if (flags & __PRINTF_FLAG_BIGCHARS) |
digits = digits_big; |
char data[PRINT_NUMBER_BUFFER_SIZE]; |
char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1]; |
*ptr-- = 0; /* Put zero at end of string */ |
/* Size of number with all prefixes and signs */ |
int size = 0; |
/* Put zero at end of string */ |
*ptr-- = 0; |
if (num == 0) { |
*ptr-- = '0'; |
size++; |
238,15 → 374,17 |
} while (num /= base); |
} |
number_size = size; |
/* Size of plain number */ |
int number_size = size; |
/* |
* Collect sum of all prefixes/signs/... to calculate padding and |
* leading zeroes |
* Collect the sum of all prefixes/signs/etc. to calculate padding and |
* leading zeroes. |
*/ |
if (flags & __PRINTF_FLAG_PREFIX) { |
switch(base) { |
case 2: /* Binary formating is not standard, but usefull */ |
case 2: |
/* Binary formating is not standard, but usefull */ |
size += 2; |
break; |
case 8: |
257,8 → 395,8 |
break; |
} |
} |
sgn = 0; |
char sgn = 0; |
if (flags & __PRINTF_FLAG_SIGNED) { |
if (flags & __PRINTF_FLAG_NEGATIVE) { |
sgn = '-'; |
271,47 → 409,46 |
size++; |
} |
} |
if (flags & __PRINTF_FLAG_LEFTALIGNED) { |
if (flags & __PRINTF_FLAG_LEFTALIGNED) |
flags &= ~__PRINTF_FLAG_ZEROPADDED; |
} |
/* |
* If number is leftaligned or precision is specified then zeropadding |
* is ignored. |
* If the number is left-aligned or precision is specified then |
* padding with zeros is ignored. |
*/ |
if (flags & __PRINTF_FLAG_ZEROPADDED) { |
if ((precision == 0) && (width > size)) { |
if ((precision == 0) && (width > size)) |
precision = width - size + number_size; |
} |
} |
/* print leading spaces */ |
/* We must print whole number not only a part. */ |
if (number_size > precision) |
/* Print leading spaces */ |
if (number_size > precision) { |
/* Print the whole number, not only a part */ |
precision = number_size; |
} |
width -= precision + size - number_size; |
size_t counter = 0; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
} |
/* print sign */ |
/* Print sign */ |
if (sgn) { |
if (printf_putchar(sgn, ps) == 1) |
counter++; |
} |
/* print prefix */ |
/* Print prefix */ |
if (flags & __PRINTF_FLAG_PREFIX) { |
switch(base) { |
case 2: /* Binary formating is not standard, but usefull */ |
case 2: |
/* Binary formating is not standard, but usefull */ |
if (printf_putchar('0', ps) == 1) |
counter++; |
if (flags & __PRINTF_FLAG_BIGCHARS) { |
339,152 → 476,154 |
break; |
} |
} |
/* print leading zeroes */ |
/* Print leading zeroes */ |
precision -= number_size; |
while (precision-- > 0) { |
while (precision-- > 0) { |
if (printf_putchar('0', ps) == 1) |
counter++; |
} |
/* print number itself */ |
if ((retval = printf_putstr(++ptr, ps)) > 0) { |
/* Print the number itself */ |
int retval; |
if ((retval = printf_putstr(++ptr, ps)) > 0) |
counter += retval; |
} |
/* print ending spaces */ |
/* Print tailing spaces */ |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
return counter; |
return ((int) counter); |
} |
/** Print formatted string. |
* |
* Print string formatted according to the fmt parameter and variadic arguments. |
* Each formatting directive must have the following form: |
* |
* \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION |
* |
* \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION |
* |
* FLAGS:@n |
* - "#" Force to print prefix. |
* For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and |
* 0X and for conversion \%b the prefix is 0b. |
* - "#" Force to print prefix. For \%o conversion, the prefix is 0, for |
* \%x and \%X prefixes are 0x and 0X and for conversion \%b the |
* prefix is 0b. |
* |
* - "-" Align to left. |
* - "-" Align to left. |
* |
* - "+" Print positive sign just as negative. |
* - "+" Print positive sign just as negative. |
* |
* - " " If the printed number is positive and "+" flag is not set, |
* print space in place of sign. |
* - " " If the printed number is positive and "+" flag is not set, |
* print space in place of sign. |
* |
* - "0" Print 0 as padding instead of spaces. Zeroes are placed between |
* sign and the rest of the number. This flag is ignored if "-" |
* flag is specified. |
* |
* - "0" Print 0 as padding instead of spaces. Zeroes are placed between |
* sign and the rest of the number. This flag is ignored if "-" |
* flag is specified. |
* |
* WIDTH:@n |
* - Specify minimal width of printed argument. If it is bigger, width is |
* ignored. If width is specified with a "*" character instead of number, |
* width is taken from parameter list. And integer parameter is expected |
* before parameter for processed conversion specification. If this value |
* is negative its absolute value is taken and the "-" flag is set. |
* - Specify the minimal width of a printed argument. If it is bigger, |
* width is ignored. If width is specified with a "*" character instead of |
* number, width is taken from parameter list. And integer parameter is |
* expected before parameter for processed conversion specification. If |
* this value is negative its absolute value is taken and the "-" flag is |
* set. |
* |
* PRECISION:@n |
* - Value precision. For numbers it specifies minimum valid numbers. |
* Smaller numbers are printed with leading zeroes. Bigger numbers are |
* not affected. Strings with more than precision characters are cut off. |
* Just as with width, an "*" can be used used instead of a number. An |
* integer value is then expected in parameters. When both width and |
* precision are specified using "*", the first parameter is used for |
* width and the second one for precision. |
* |
* - Value precision. For numbers it specifies minimum valid numbers. |
* Smaller numbers are printed with leading zeroes. Bigger numbers are not |
* affected. Strings with more than precision characters are cut off. Just |
* as with width, an "*" can be used used instead of a number. An integer |
* value is then expected in parameters. When both width and precision are |
* specified using "*", the first parameter is used for width and the |
* second one for precision. |
* |
* TYPE:@n |
* - "hh" Signed or unsigned char.@n |
* - "h" Signed or usigned short.@n |
* - "" Signed or usigned int (default value).@n |
* - "l" Signed or usigned long int.@n |
* - "ll" Signed or usigned long long int.@n |
* - "z" Type size_t.@n |
* |
* |
* - "hh" Signed or unsigned char.@n |
* - "h" Signed or unsigned short.@n |
* - "" Signed or unsigned int (default value).@n |
* - "l" Signed or unsigned long int.@n |
* If conversion is "c", the character is wchar_t (wide character).@n |
* If conversion is "s", the string is wchar_t * (wide string).@n |
* - "ll" Signed or unsigned long long int.@n |
* |
* CONVERSION:@n |
* - % Print percentile character itself. |
* - % Print percentile character itself. |
* |
* - c Print single character. |
* - c Print single character. The character is expected to be plain |
* ASCII (e.g. only values 0 .. 127 are valid).@n |
* If type is "l", then the character is expected to be wide character |
* (e.g. values 0 .. 0x10ffff are valid). |
* |
* - s Print zero terminated string. If a NULL value is passed as |
* value, "(NULL)" is printed instead. |
* |
* - P, p Print value of a pointer. Void * value is expected and it is |
* printed in hexadecimal notation with prefix (as with '\%#X' or |
* '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers). |
* - s Print zero terminated string. If a NULL value is passed as |
* value, "(NULL)" is printed instead.@n |
* If type is "l", then the string is expected to be wide string. |
* |
* - b Print value as unsigned binary number. Prefix is not printed by |
* default. (Nonstandard extension.) |
* |
* - o Print value as unsigned octal number. Prefix is not printed by |
* default. |
* - P, p Print value of a pointer. Void * value is expected and it is |
* printed in hexadecimal notation with prefix (as with \%#X / \%#x |
* for 32-bit or \%#X / \%#x for 64-bit long pointers). |
* |
* - d, i Print signed decimal number. There is no difference between d |
* and i conversion. |
* - b Print value as unsigned binary number. Prefix is not printed by |
* default. (Nonstandard extension.) |
* |
* - u Print unsigned decimal number. |
* - o Print value as unsigned octal number. Prefix is not printed by |
* default. |
* |
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is |
* not printed by default. |
* |
* All other characters from fmt except the formatting directives are printed in |
* - d, i Print signed decimal number. There is no difference between d |
* and i conversion. |
* |
* - u Print unsigned decimal number. |
* |
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is |
* not printed by default. |
* |
* All other characters from fmt except the formatting directives are printed |
* verbatim. |
* |
* @param fmt Formatting NULL terminated string. |
* @return Number of printed characters or negative value on failure. |
* @param fmt Format NULL-terminated string. |
* |
* @return Number of characters printed, negative value on failure. |
* |
*/ |
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) |
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap) |
{ |
/* i is the index of the currently processed char from fmt */ |
int i = 0; |
/* j is the index to the first not printed nonformating character */ |
int j = 0; |
int end; |
int counter; /* counter of printed characters */ |
int retval; /* used to store return values from called functions */ |
char c; |
qualifier_t qualifier; /* type of argument */ |
int base; /* base in which will be a numeric parameter printed */ |
uint64_t number; /* argument value */ |
size_t size; /* byte size of integer parameter */ |
int width, precision; |
uint64_t flags; |
size_t i; /* Index of the currently processed character from fmt */ |
size_t nxt = 0; /* Index of the next character from fmt */ |
size_t j = 0; /* Index to the first not printed nonformating character */ |
counter = 0; |
size_t counter = 0; /* Number of characters printed */ |
int retval; /* Return values from nested functions */ |
while ((c = fmt[i])) { |
/* control character */ |
if (c == '%' ) { |
/* print common characters if any processed */ |
while (true) { |
i = nxt; |
wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
/* Control character */ |
if (uc == '%') { |
/* Print common characters if any processed */ |
if (i > j) { |
if ((retval = printf_putnchars(&fmt[j], |
(size_t)(i - j), ps)) < 0) { /* error */ |
goto minus_out; |
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { |
/* Error */ |
counter = -counter; |
goto out; |
} |
counter += retval; |
} |
j = i; |
/* parse modifiers */ |
flags = 0; |
end = 0; |
/* Parse modifiers */ |
uint32_t flags = 0; |
bool end = false; |
do { |
++i; |
switch (c = fmt[i]) { |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
switch (uc) { |
case '#': |
flags |= __PRINTF_FLAG_PREFIX; |
break; |
501,114 → 640,145 |
flags |= __PRINTF_FLAG_ZEROPADDED; |
break; |
default: |
end = 1; |
}; |
} while (end == 0); |
end = true; |
}; |
} while (!end); |
/* width & '*' operator */ |
width = 0; |
if (isdigit(fmt[i])) { |
while (isdigit(fmt[i])) { |
/* Width & '*' operator */ |
int width = 0; |
if (isdigit(uc)) { |
while (true) { |
width *= 10; |
width += fmt[i++] - '0'; |
width += uc - '0'; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
if (!isdigit(uc)) |
break; |
} |
} else if (fmt[i] == '*') { |
/* get width value from argument list*/ |
i++; |
width = (int)va_arg(ap, int); |
} else if (uc == '*') { |
/* Get width value from argument list */ |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
width = (int) va_arg(ap, int); |
if (width < 0) { |
/* negative width sets '-' flag */ |
/* Negative width sets '-' flag */ |
width *= -1; |
flags |= __PRINTF_FLAG_LEFTALIGNED; |
} |
} |
/* precision and '*' operator */ |
precision = 0; |
if (fmt[i] == '.') { |
++i; |
if (isdigit(fmt[i])) { |
while (isdigit(fmt[i])) { |
/* Precision and '*' operator */ |
int precision = 0; |
if (uc == '.') { |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (isdigit(uc)) { |
while (true) { |
precision *= 10; |
precision += fmt[i++] - '0'; |
precision += uc - '0'; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
if (!isdigit(uc)) |
break; |
} |
} else if (fmt[i] == '*') { |
/* get precision value from argument */ |
i++; |
precision = (int)va_arg(ap, int); |
} else if (uc == '*') { |
/* Get precision value from the argument list */ |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
precision = (int) va_arg(ap, int); |
if (precision < 0) { |
/* negative precision ignored */ |
/* Ignore negative precision */ |
precision = 0; |
} |
} |
} |
switch (fmt[i++]) { |
/** @todo unimplemented qualifiers: |
* t ptrdiff_t - ISO C 99 |
qualifier_t qualifier; |
switch (uc) { |
/** @todo Unimplemented qualifiers: |
* t ptrdiff_t - ISO C 99 |
*/ |
case 'h': /* char or short */ |
case 'h': |
/* Char or short */ |
qualifier = PrintfQualifierShort; |
if (fmt[i] == 'h') { |
i++; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 'h') { |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
qualifier = PrintfQualifierByte; |
} |
break; |
case 'l': /* long or long long*/ |
case 'l': |
/* Long or long long */ |
qualifier = PrintfQualifierLong; |
if (fmt[i] == 'l') { |
i++; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 'l') { |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
qualifier = PrintfQualifierLongLong; |
} |
break; |
case 'z': /* size_t */ |
qualifier = PrintfQualifierSizeT; |
break; |
default: |
/* set default type */ |
/* Default type */ |
qualifier = PrintfQualifierInt; |
--i; |
} |
} |
base = 10; |
switch (c = fmt[i]) { |
unsigned int base = 10; |
switch (uc) { |
/* |
* String and character conversions. |
*/ |
case 's': |
if ((retval = print_string(va_arg(ap, char*), |
width, precision, flags, ps)) < 0) { |
goto minus_out; |
if (qualifier == PrintfQualifierLong) |
retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps); |
else |
retval = print_str(va_arg(ap, char *), width, precision, flags, ps); |
if (retval < 0) { |
counter = -counter; |
goto out; |
} |
counter += retval; |
j = i + 1; |
j = nxt; |
goto next_char; |
case 'c': |
c = va_arg(ap, unsigned int); |
retval = print_char(c, width, flags, ps); |
if (qualifier == PrintfQualifierLong) |
retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps); |
else |
retval = print_char(va_arg(ap, unsigned int), width, flags, ps); |
if (retval < 0) { |
goto minus_out; |
} |
counter = -counter; |
goto out; |
}; |
counter += retval; |
j = i + 1; |
j = nxt; |
goto next_char; |
/* |
/* |
* Integer values |
*/ |
case 'P': /* pointer */ |
flags |= __PRINTF_FLAG_BIGCHARS; |
case 'P': |
/* Pointer */ |
flags |= __PRINTF_FLAG_BIGCHARS; |
case 'p': |
flags |= __PRINTF_FLAG_PREFIX; |
base = 16; |
qualifier = PrintfQualifierPointer; |
break; |
case 'b': |
break; |
case 'b': |
base = 2; |
break; |
case 'o': |
616,7 → 786,7 |
break; |
case 'd': |
case 'i': |
flags |= __PRINTF_FLAG_SIGNED; |
flags |= __PRINTF_FLAG_SIGNED; |
case 'u': |
break; |
case 'X': |
624,66 → 794,63 |
case 'x': |
base = 16; |
break; |
/* percentile itself */ |
case '%': |
/* Percentile itself */ |
case '%': |
j = i; |
goto next_char; |
/* |
* Bad formatting. |
*/ |
default: |
/* |
* Unknown format. Now, j is the index of '%', |
* so we will print the whole bad format |
* sequence. |
* Unknown format. Now, j is the index of '%' |
* so we will print whole bad format sequence. |
*/ |
goto next_char; |
goto next_char; |
} |
/* Print integers */ |
size_t size; |
uint64_t number; |
switch (qualifier) { |
case PrintfQualifierByte: |
size = sizeof(unsigned char); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierShort: |
size = sizeof(unsigned short); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierInt: |
size = sizeof(unsigned int); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierLong: |
size = sizeof(unsigned long); |
number = (uint64_t)va_arg(ap, unsigned long); |
number = (uint64_t) va_arg(ap, unsigned long); |
break; |
case PrintfQualifierLongLong: |
size = sizeof(unsigned long long); |
number = (uint64_t)va_arg(ap, |
unsigned long long); |
number = (uint64_t) va_arg(ap, unsigned long long); |
break; |
case PrintfQualifierPointer: |
size = sizeof(void *); |
number = (uint64_t)(unsigned long)va_arg(ap, |
void *); |
number = (uint64_t) (unsigned long) va_arg(ap, void *); |
break; |
case PrintfQualifierSizeT: |
size = sizeof(size_t); |
number = (uint64_t)va_arg(ap, size_t); |
break; |
default: /* Unknown qualifier */ |
goto minus_out; |
default: |
/* Unknown qualifier */ |
counter = -counter; |
goto out; |
} |
if (flags & __PRINTF_FLAG_SIGNED) { |
if (number & (0x1 << (size * 8 - 1))) { |
flags |= __PRINTF_FLAG_NEGATIVE; |
if (size == sizeof(uint64_t)) { |
number = -((int64_t)number); |
number = -((int64_t) number); |
} else { |
number = ~number; |
number &= |
693,31 → 860,31 |
} |
} |
} |
if ((retval = print_number(number, width, precision, |
base, flags, ps)) < 0 ) { |
goto minus_out; |
base, flags, ps)) < 0) { |
counter = -counter; |
goto out; |
} |
counter += retval; |
j = i + 1; |
} |
j = nxt; |
} |
next_char: |
++i; |
; |
} |
if (i > j) { |
retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps); |
if (retval < 0) { /* error */ |
goto minus_out; |
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { |
/* Error */ |
counter = -counter; |
goto out; |
} |
counter += retval; |
} |
return counter; |
minus_out: |
return -counter; |
out: |
return ((int) counter); |
} |
/** @} |
/branches/arm/uspace/lib/libc/generic/io/vprintf.c |
---|
38,39 → 38,81 |
#include <io/printf_core.h> |
#include <futex.h> |
#include <async.h> |
#include <string.h> |
static atomic_t printf_futex = FUTEX_INITIALIZER; |
static int vprintf_write(const char *str, size_t count, void *unused) |
static int vprintf_str_write(const char *str, size_t size, void *stream) |
{ |
return write_stdout(str, count); |
size_t wr = fwrite(str, 1, size, (FILE *) stream); |
return str_nlength(str, wr); |
} |
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream) |
{ |
size_t offset = 0; |
size_t chars = 0; |
while (offset < size) { |
if (fputc(str[chars], (FILE *) stream) <= 0) |
break; |
chars++; |
offset += sizeof(wchar_t); |
} |
return chars; |
} |
/** Print formatted text. |
* @param fmt format string |
* @param ap format parameters |
* |
* @param stream Output stream |
* @param fmt Format string |
* @param ap Format parameters |
* |
* \see For more details about format string see printf_core. |
* |
*/ |
int vprintf(const char *fmt, va_list ap) |
int vfprintf(FILE *stream, const char *fmt, va_list ap) |
{ |
struct printf_spec ps = { |
(int (*)(void *, size_t, void *)) vprintf_write, |
NULL |
vprintf_str_write, |
vprintf_wstr_write, |
stream |
}; |
/* |
* Prevent other threads to execute printf_core() |
*/ |
futex_down(&printf_futex); |
/* |
* Prevent other pseudo threads of the same thread |
* Prevent other fibrils of the same thread |
* to execute printf_core() |
*/ |
async_serialize_start(); |
int ret = printf_core(fmt, &ps, ap); |
async_serialize_end(); |
futex_up(&printf_futex); |
return ret; |
} |
/** Print formatted text to stdout. |
* |
* @param file Output stream |
* @param fmt Format string |
* @param ap Format parameters |
* |
* \see For more details about format string see printf_core. |
* |
*/ |
int vprintf(const char *fmt, va_list ap) |
{ |
return vfprintf(stdout, fmt, ap); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/io/printf.c |
---|
34,23 → 34,43 |
#include <io/printf_core.h> |
#include <stdio.h> |
#include <stdio.h> |
/** Print formatted text. |
* @param fmt format string |
* |
* @param stream Output stream |
* @param fmt Format string |
* |
* \see For more details about format string see printf_core. |
* |
*/ |
int fprintf(FILE *stream, const char *fmt, ...) |
{ |
va_list args; |
va_start(args, fmt); |
int ret = vfprintf(stream, fmt, args); |
va_end(args); |
return ret; |
} |
/** Print formatted text to stdout. |
* |
* @param fmt Format string |
* |
* \see For more details about format string see printf_core. |
* |
*/ |
int printf(const char *fmt, ...) |
{ |
int ret; |
va_list args; |
va_start(args, fmt); |
ret = vprintf(fmt, args); |
int ret = vprintf(fmt, args); |
va_end(args); |
return ret; |
} |
/branches/arm/uspace/lib/libc/generic/io/snprintf.c |
---|
37,21 → 37,23 |
#include <io/printf_core.h> |
/** Print formatted to the given buffer with limited size. |
* @param str buffer |
* @param size buffer size |
* @param fmt format string |
* |
* @param str Buffer |
* @param size Buffer size |
* @param fmt Format string |
* |
* \see For more details about format string see printf_core. |
* |
*/ |
int snprintf(char *str, size_t size, const char *fmt, ...) |
{ |
int ret; |
va_list args; |
va_start(args, fmt); |
va_start(args, fmt); |
ret = vsnprintf(str, size, fmt, args); |
int ret = vsnprintf(str, size, fmt, args); |
va_end(args); |
return ret; |
} |
/branches/arm/uspace/lib/libc/generic/io/asprintf.c |
---|
36,42 → 36,52 |
#include <stdarg.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <io/printf_core.h> |
static int asprintf_prewrite(const char *str, size_t count, void *unused) |
static int asprintf_str_write(const char *str, size_t count, void *unused) |
{ |
return count; |
return str_nlength(str, count); |
} |
static int asprintf_wstr_write(const wchar_t *str, size_t count, void *unused) |
{ |
return wstr_nlength(str, count); |
} |
/** Allocate and print to string. |
* |
* @param strp Address of the pointer where to store the address of |
* the newly allocated string. |
* @fmt Format strin. |
* @param strp Address of the pointer where to store the address of |
* the newly allocated string. |
* @fmt Format string. |
* |
* @return Number of characters printed or a negative error code. |
* @return Number of characters printed or a negative error code. |
* |
*/ |
int asprintf(char **strp, const char *fmt, ...) |
{ |
struct printf_spec ps = { |
asprintf_prewrite, |
NULL |
asprintf_str_write, |
asprintf_wstr_write, |
NULL |
}; |
int ret; |
va_list args; |
va_start(args, fmt); |
ret = printf_core(fmt, &ps, args); |
int ret = printf_core(fmt, &ps, args); |
va_end(args); |
if (ret > 0) { |
*strp = malloc(ret + 20); |
if (!*strp) |
*strp = malloc(STR_BOUNDS(ret) + 1); |
if (*strp == NULL) |
return -1; |
va_start(args, fmt); |
vsprintf(*strp, fmt, args); |
va_end(args); |
vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args); |
va_end(args); |
} |
return ret; |
} |
/branches/arm/uspace/lib/libc/generic/io/vsnprintf.c |
---|
36,87 → 36,145 |
#include <stdio.h> |
#include <string.h> |
#include <io/printf_core.h> |
#include <errno.h> |
struct vsnprintf_data { |
size_t size; /* total space for string */ |
size_t len; /* count of currently used characters */ |
char *string; /* destination string */ |
}; |
typedef struct { |
size_t size; /* Total size of the buffer (in bytes) */ |
size_t len; /* Number of already used bytes */ |
char *dst; /* Destination */ |
} vsnprintf_data_t; |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 |
* has snprintf to return number of characters that would have been written if |
* enough space had been available. Hence the return value is not number of |
* really printed characters but size of input string. Number of really used |
* characters is stored in data->len. |
* |
* @param str Source string to print. |
* @param count Size of the source string. |
* @param data Structure with destination string, counter of used space |
* and total string size. |
* @return Number of characters to print (not characters really |
* printed!) |
* Write at most data->size plain characters including trailing zero. |
* According to C99, snprintf() has to return number of characters that |
* would have been written if enough space had been available. Hence |
* the return value is not the number of actually printed characters |
* but size of the input string. |
* |
* @param str Source string to print. |
* @param size Number of plain characters in str. |
* @param data Structure describing destination string, counter |
* of used space and total string size. |
* |
* @return Number of characters to print (not characters actually |
* printed). |
* |
*/ |
static int |
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data) |
{ |
size_t i; |
i = data->size - data->len; |
if (i == 0) { |
return count; |
} |
size_t left = data->size - data->len; |
if (i == 1) { |
/* |
* We have only one free byte left in buffer => write there |
* trailing zero. |
if (left == 0) |
return ((int) size); |
if (left == 1) { |
/* We have only one free byte left in buffer |
* -> store trailing zero |
*/ |
data->string[data->size - 1] = 0; |
data->dst[data->size - 1] = 0; |
data->len = data->size; |
return count; |
return ((int) size); |
} |
if (i <= count) { |
/* |
* We have not enought space for whole string with the trailing |
* zero => print only a part of string. |
if (left <= size) { |
/* We do not have enough space for the whole string |
* with the trailing zero => print only a part |
* of string |
*/ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
size_t index = 0; |
while (index < size) { |
wchar_t uc = str_decode(str, &index, size); |
if (chr_encode(uc, data->dst, &data->len, data->size - 1) != EOK) |
break; |
} |
/* Put trailing zero at end, but not count it |
* into data->len so it could be rewritten next time |
*/ |
data->dst[data->len] = 0; |
return ((int) size); |
} |
/* Buffer is big enought to print whole string */ |
memcpy((void *)(data->string + data->len), (void *)str, count); |
data->len += count; |
/* |
* Put trailing zero at end, but not count it into data->len so it could |
* be rewritten next time. |
/* Buffer is big enought to print the whole string */ |
memcpy((void *)(data->dst + data->len), (void *) str, size); |
data->len += size; |
/* Put trailing zero at end, but not count it |
* into data->len so it could be rewritten next time |
*/ |
data->string[data->len] = 0; |
data->dst[data->len] = 0; |
return ((int) size); |
} |
return count; |
/** Write wide string to given buffer. |
* |
* Write at most data->size plain characters including trailing zero. |
* According to C99, snprintf() has to return number of characters that |
* would have been written if enough space had been available. Hence |
* the return value is not the number of actually printed characters |
* but size of the input string. |
* |
* @param str Source wide string to print. |
* @param size Number of bytes in str. |
* @param data Structure describing destination string, counter |
* of used space and total string size. |
* |
* @return Number of wide characters to print (not characters actually |
* printed). |
* |
*/ |
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data) |
{ |
size_t index = 0; |
while (index < (size / sizeof(wchar_t))) { |
size_t left = data->size - data->len; |
if (left == 0) |
return ((int) size); |
if (left == 1) { |
/* We have only one free byte left in buffer |
* -> store trailing zero |
*/ |
data->dst[data->size - 1] = 0; |
data->len = data->size; |
return ((int) size); |
} |
if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != EOK) |
break; |
index++; |
} |
/* Put trailing zero at end, but not count it |
* into data->len so it could be rewritten next time |
*/ |
data->dst[data->len] = 0; |
return ((int) size); |
} |
/** Print formatted to the given buffer with limited size. |
* @param str Buffer. |
* @param size Bffer size. |
* @param fmt Format string. |
* \see For more details about format string see printf_core. |
*/ |
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
{ |
struct vsnprintf_data data = {size, 0, str}; |
struct printf_spec ps = { |
(int(*)(void *, size_t, void *)) vsnprintf_write, |
vsnprintf_data_t data = { |
size, |
0, |
str |
}; |
printf_spec_t ps = { |
(int(*) (const char *, size_t, void *)) vsnprintf_str_write, |
(int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write, |
&data |
}; |
/* |
* Print 0 at end of string - fix the case that nothing will be printed. |
*/ |
/* Print 0 at end of string - fix the case that nothing will be printed */ |
if (size > 0) |
str[0] = 0; |
/branches/arm/uspace/lib/libc/generic/io/klog.c |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2006 Josef Cejka |
* Copyright (c) 2006 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <string.h> |
#include <sys/types.h> |
#include <unistd.h> |
#include <io/klog.h> |
size_t klog_write(const void *buf, size_t size) |
{ |
return (size_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/malloc.c |
---|
0,0 → 1,475 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Petr Tuma |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <malloc.h> |
#include <bool.h> |
#include <as.h> |
#include <align.h> |
#include <macros.h> |
#include <assert.h> |
#include <errno.h> |
#include <bitops.h> |
#include <mem.h> |
#include <adt/gcdlcm.h> |
/* Magic used in heap headers. */ |
#define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101 |
/* Magic used in heap footers. */ |
#define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202 |
/** Allocation alignment (this also covers the alignment of fields |
in the heap header and footer) */ |
#define BASE_ALIGN 16 |
/** |
* Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28) |
/** |
* |
*/ |
#define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) |
/** |
* Calculate real size of a heap block (with header and footer) |
*/ |
#define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD) |
/** |
* Calculate net size of a heap block (without header and footer) |
*/ |
#define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) |
/** Header of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* Indication of a free block */ |
bool free; |
/* A magic value to detect overwrite of heap header */ |
uint32_t magic; |
} heap_block_head_t; |
/** Footer of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* A magic value to detect overwrite of heap footer */ |
uint32_t magic; |
} heap_block_foot_t; |
/** Linker heap symbol */ |
extern char _heap; |
/** Address of heap start */ |
static void *heap_start = 0; |
/** Address of heap end */ |
static void *heap_end = 0; |
/** Maximum heap size */ |
static size_t max_heap_size = (size_t) -1; |
/** Current number of pages of heap area */ |
static size_t heap_pages = 0; |
/** Initialize a heap block |
* |
* Fills in the structures related to a heap block. |
* |
* @param addr Address of the block. |
* @param size Size of the block including the header and the footer. |
* @param free Indication of a free block. |
* |
*/ |
static void block_init(void *addr, size_t size, bool free) |
{ |
/* Calculate the position of the header and the footer */ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t)); |
head->size = size; |
head->free = free; |
head->magic = HEAP_BLOCK_HEAD_MAGIC; |
foot->size = size; |
foot->magic = HEAP_BLOCK_FOOT_MAGIC; |
} |
/** Check a heap block |
* |
* Verifies that the structures related to a heap block still contain |
* the magic constants. This helps detect heap corruption early on. |
* |
* @param addr Address of the block. |
* |
*/ |
static void block_check(void *addr) |
{ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
assert(head->magic == HEAP_BLOCK_HEAD_MAGIC); |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t)); |
assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC); |
assert(head->size == foot->size); |
} |
static bool grow_heap(size_t size) |
{ |
if (size == 0) |
return false; |
size_t heap_size = (size_t) (heap_end - heap_start); |
if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size)) |
return false; |
size_t pages = (size - 1) / PAGE_SIZE + 1; |
if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0) |
== EOK) { |
void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) + |
(heap_pages + pages) * PAGE_SIZE, BASE_ALIGN); |
block_init(heap_end, end - heap_end, true); |
heap_pages += pages; |
heap_end = end; |
return true; |
} |
return false; |
} |
static void shrink_heap(void) |
{ |
// TODO |
} |
/** Initialize the heap allocator |
* |
* Finds how much physical memory we have and creates |
* the heap management structures that mark the whole |
* physical memory as a single free block. |
* |
*/ |
void __heap_init(void) |
{ |
if (as_area_create((void *) &_heap, PAGE_SIZE, |
AS_AREA_WRITE | AS_AREA_READ)) { |
heap_pages = 1; |
heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN); |
heap_end = |
(void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN); |
/* Make the entire area one large block. */ |
block_init(heap_start, heap_end - heap_start, true); |
} |
} |
uintptr_t get_max_heap_addr(void) |
{ |
if (max_heap_size == (size_t) -1) |
max_heap_size = |
max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE); |
return ((uintptr_t) heap_start + max_heap_size); |
} |
static void split_mark(heap_block_head_t *cur, const size_t size) |
{ |
assert(cur->size >= size); |
/* See if we should split the block. */ |
size_t split_limit = GROSS_SIZE(size); |
if (cur->size > split_limit) { |
/* Block big enough -> split. */ |
void *next = ((void *) cur) + size; |
block_init(next, cur->size - size, true); |
block_init(cur, size, false); |
} else { |
/* Block too small -> use as is. */ |
cur->free = false; |
} |
} |
/** Allocate a memory block |
* |
* @param size The size of the block to allocate. |
* @param align Memory address alignment. |
* |
* @return the address of the block or NULL when not enough memory. |
* |
*/ |
static void *malloc_internal(const size_t size, const size_t align) |
{ |
if (align == 0) |
return NULL; |
size_t falign = lcm(align, BASE_ALIGN); |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); |
bool grown = false; |
void *result; |
loop: |
result = NULL; |
heap_block_head_t *cur = (heap_block_head_t *) heap_start; |
while ((result == NULL) && ((void *) cur < heap_end)) { |
block_check(cur); |
/* Try to find a block that is free and large enough. */ |
if ((cur->free) && (cur->size >= real_size)) { |
/* We have found a suitable block. |
Check for alignment properties. */ |
void *addr = ((void *) cur) + sizeof(heap_block_head_t); |
void *aligned = (void *) ALIGN_UP(addr, falign); |
if (addr == aligned) { |
/* Exact block start including alignment. */ |
split_mark(cur, real_size); |
result = addr; |
} else { |
/* Block start has to be aligned */ |
size_t excess = (size_t) (aligned - addr); |
if (cur->size >= real_size + excess) { |
/* The current block is large enough to fit |
data in including alignment */ |
if ((void *) cur > heap_start) { |
/* There is a block before the current block. |
This previous block can be enlarged to compensate |
for the alignment excess */ |
heap_block_foot_t *prev_foot = |
((void *) cur) - sizeof(heap_block_foot_t); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) cur) - prev_foot->size); |
block_check(prev_head); |
size_t reduced_size = cur->size - excess; |
heap_block_head_t *next_head = ((void *) cur) + excess; |
if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) { |
/* The previous block is not free and there is enough |
space to fill in a new free block between the previous |
and current block */ |
block_init(cur, excess, true); |
} else { |
/* The previous block is free (thus there is no need to |
induce additional fragmentation to the heap) or the |
excess is small, thus just enlarge the previous block */ |
block_init(prev_head, prev_head->size + excess, prev_head->free); |
} |
block_init(next_head, reduced_size, true); |
split_mark(next_head, real_size); |
result = aligned; |
cur = next_head; |
} else { |
/* The current block is the first block on the heap. |
We have to make sure that the alignment excess |
is large enough to fit a new free block just |
before the current block */ |
while (excess < STRUCT_OVERHEAD) { |
aligned += falign; |
excess += falign; |
} |
/* Check for current block size again */ |
if (cur->size >= real_size + excess) { |
size_t reduced_size = cur->size - excess; |
cur = (heap_block_head_t *) (heap_start + excess); |
block_init(heap_start, excess, true); |
block_init(cur, reduced_size, true); |
split_mark(cur, real_size); |
result = aligned; |
} |
} |
} |
} |
} |
/* Advance to the next block. */ |
cur = (heap_block_head_t *) (((void *) cur) + cur->size); |
} |
if ((result == NULL) && (!grown)) { |
if (grow_heap(real_size)) { |
grown = true; |
goto loop; |
} |
} |
return result; |
} |
void *malloc(const size_t size) |
{ |
return malloc_internal(size, BASE_ALIGN); |
} |
void *memalign(const size_t align, const size_t size) |
{ |
if (align == 0) |
return NULL; |
size_t palign = |
1 << (fnzb(max(sizeof(void *), align) - 1) + 1); |
return malloc_internal(size, palign); |
} |
void *realloc(const void *addr, const size_t size) |
{ |
if (addr == NULL) |
return malloc(size); |
/* Calculate the position of the header. */ |
heap_block_head_t *head = |
(heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
void *ptr = NULL; |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN)); |
size_t orig_size = head->size; |
if (orig_size > real_size) { |
/* Shrink */ |
if (orig_size - real_size >= STRUCT_OVERHEAD) { |
/* Split the original block to a full block |
and a tailing free block */ |
block_init((void *) head, real_size, false); |
block_init((void *) head + real_size, |
orig_size - real_size, true); |
shrink_heap(); |
} |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
/* Look at the next block. If it is free and the size is |
sufficient then merge the two. */ |
heap_block_head_t *next_head = |
(heap_block_head_t *) (((void *) head) + head->size); |
if (((void *) next_head < heap_end) && |
(head->size + next_head->size >= real_size) && |
(next_head->free)) { |
block_check(next_head); |
block_init(head, head->size + next_head->size, false); |
split_mark(head, ALIGN_UP(size, BASE_ALIGN)); |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
ptr = malloc(size); |
if (ptr != NULL) { |
memcpy(ptr, addr, NET_SIZE(orig_size)); |
free(addr); |
} |
} |
} |
return ptr; |
} |
/** Free a memory block |
* |
* @param addr The address of the block. |
*/ |
void free(const void *addr) |
{ |
/* Calculate the position of the header. */ |
heap_block_head_t *head |
= (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
/* Mark the block itself as free. */ |
head->free = true; |
/* Look at the next block. If it is free, merge the two. */ |
heap_block_head_t *next_head |
= (heap_block_head_t *) (((void *) head) + head->size); |
if ((void *) next_head < heap_end) { |
block_check(next_head); |
if (next_head->free) |
block_init(head, head->size + next_head->size, true); |
} |
/* Look at the previous block. If it is free, merge the two. */ |
if ((void *) head > heap_start) { |
heap_block_foot_t *prev_foot = |
(heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t)); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) head) - prev_foot->size); |
block_check(prev_head); |
if (prev_head->free) |
block_init(prev_head, prev_head->size + head->size, true); |
} |
shrink_heap(); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/fibril.c |
---|
33,7 → 33,7 |
/** @file |
*/ |
#include <libadt/list.h> |
#include <adt/list.h> |
#include <fibril.h> |
#include <thread.h> |
#include <tls.h> |
49,7 → 49,8 |
#define FIBRIL_INITIAL_STACK_PAGES_NO 1 |
#endif |
/** This futex serializes access to ready_list, serialized_list and manage_list. |
/** |
* This futex serializes access to ready_list, serialized_list and manager_list. |
*/ |
static atomic_t fibril_futex = FUTEX_INITIALIZER; |
59,12 → 60,12 |
static void fibril_main(void); |
/** Number of fibrils that are in async_serialized mode */ |
static int serialized_fibrils; /* Protected by async_futex */ |
/** Thread-local count of serialization. If >0, we must not preempt */ |
static __thread int serialization_count; |
/** Counter for fibrils residing in async_manager */ |
static int fibrils_in_manager; |
/** Number of threads that are executing a manager fibril. */ |
static int threads_in_manager; |
/** Number of threads that are executing a manager fibril and are serialized. */ |
static int serialized_threads; /* Protected by async_futex */ |
/** Fibril-local count of serialization. If > 0, we must not preempt */ |
static fibril_local int serialization_count; |
/** Setup fibril information into TCB structure */ |
fibril_t *fibril_setup(void) |
143,11 → 144,11 |
if (list_empty(&ready_list) && list_empty(&serialized_list)) |
goto ret_0; |
/* |
* Do not preempt if there is not sufficient count of fibril |
* managers. |
* Do not preempt if there is not enough threads to run the |
* ready fibrils which are not serialized. |
*/ |
if (list_empty(&serialized_list) && |
fibrils_in_manager <= serialized_fibrils) { |
threads_in_manager <= serialized_threads) { |
goto ret_0; |
} |
} |
194,7 → 195,7 |
list_append(&srcf->link, &ready_list); |
else if (stype == FIBRIL_FROM_MANAGER) { |
list_append(&srcf->link, &manager_list); |
fibrils_in_manager--; |
threads_in_manager--; |
} else { |
/* |
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to |
208,10 → 209,10 |
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { |
dstf = list_get_instance(manager_list.next, fibril_t, link); |
if (serialization_count && stype == FIBRIL_TO_MANAGER) { |
serialized_fibrils++; |
serialized_threads++; |
srcf->flags |= FIBRIL_SERIALIZED; |
} |
fibrils_in_manager++; |
threads_in_manager++; |
if (stype == FIBRIL_FROM_DEAD) |
dstf->clean_after_me = srcf; |
219,7 → 220,7 |
if (!list_empty(&serialized_list)) { |
dstf = list_get_instance(serialized_list.next, fibril_t, |
link); |
serialized_fibrils--; |
serialized_threads--; |
} else { |
dstf = list_get_instance(ready_list.next, fibril_t, |
link); |
269,7 → 270,7 |
/** Add a fibril to the ready list. |
* |
* @param fid Pinter to the fibril structure of the fibril to be |
* @param fid Pointer to the fibril structure of the fibril to be |
* added. |
*/ |
void fibril_add_ready(fid_t fid) |
287,7 → 288,8 |
/** Add a fibril to the manager list. |
* |
* @param fid Pinter to the fibril structure of the fibril to be added. |
* @param fid Pointer to the fibril structure of the fibril to be |
* added. |
*/ |
void fibril_add_manager(fid_t fid) |
{ |
314,7 → 316,8 |
/** Return fibril id of the currently running fibril. |
* |
* @return Fibril ID of the currently running pseudo thread. |
* @return fibril ID of the currently running fibril. |
* |
*/ |
fid_t fibril_get_id(void) |
{ |
321,13 → 324,14 |
return (fid_t) __tcb_get()->fibril_data; |
} |
/** Disable preemption |
/** Disable preemption |
* |
* If the fibril wants to send several message in a row and does not want to be |
* preempted, it should start async_serialize_start() in the beginning of |
* communication and async_serialize_end() in the end. If it is a true |
* multithreaded application, it should protect the communication channel by a |
* futex as well. Interrupt messages can still be preempted. |
* futex as well. |
* |
*/ |
void fibril_inc_sercount(void) |
{ |
/branches/arm/uspace/lib/libc/generic/task.c |
---|
31,7 → 31,7 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <task.h> |
#include <libc.h> |
38,74 → 38,133 |
#include <stdlib.h> |
#include <errno.h> |
#include <loader/loader.h> |
#include <string.h> |
#include <ipc/ns.h> |
#include <macros.h> |
#include <async.h> |
task_id_t task_get_id(void) |
{ |
task_id_t task_id; |
(void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id); |
return task_id; |
} |
/** Set the task name. |
* |
* @param name The new name, typically the command used to execute the |
* program. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int task_set_name(const char *name) |
{ |
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, str_size(name)); |
} |
/** Create a new task by running an executable from the filesystem. |
* |
* This is really just a convenience wrapper over the more complicated |
* loader API. |
* |
* @param path pathname of the binary to execute |
* @param argv command-line arguments |
* @return ID of the newly created task or zero on error. |
* @param path pathname of the binary to execute |
* @param argv command-line arguments |
* |
* @return ID of the newly created task or zero on error. |
* |
*/ |
task_id_t task_spawn(const char *path, char *const argv[]) |
task_id_t task_spawn(const char *path, char *const args[]) |
{ |
loader_t *ldr; |
task_id_t task_id; |
int rc; |
/* Spawn a program loader. */ |
ldr = loader_spawn(); |
/* Connect to a program loader. */ |
loader_t *ldr = loader_connect(); |
if (ldr == NULL) |
return 0; |
/* Get task ID. */ |
rc = loader_get_task_id(ldr, &task_id); |
task_id_t task_id; |
int rc = loader_get_task_id(ldr, &task_id); |
if (rc != EOK) |
goto error; |
/* Send program pathname. */ |
rc = loader_set_pathname(ldr, path); |
if (rc != EOK) |
goto error; |
/* Send arguments. */ |
rc = loader_set_args(ldr, argv); |
rc = loader_set_args(ldr, args); |
if (rc != EOK) |
goto error; |
/* Send default files */ |
fdi_node_t *files[4]; |
fdi_node_t stdin_node; |
fdi_node_t stdout_node; |
fdi_node_t stderr_node; |
if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK)) |
files[0] = &stdin_node; |
else |
files[0] = NULL; |
if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK)) |
files[1] = &stdout_node; |
else |
files[1] = NULL; |
if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK)) |
files[2] = &stderr_node; |
else |
files[2] = NULL; |
files[3] = NULL; |
rc = loader_set_files(ldr, files); |
if (rc != EOK) |
goto error; |
/* Load the program. */ |
rc = loader_load_program(ldr); |
if (rc != EOK) |
goto error; |
/* Run it. */ |
/* Load the program. */ |
rc = loader_run(ldr); |
if (rc != EOK) |
goto error; |
/* Success */ |
free(ldr); |
return task_id; |
error: |
/* Error exit */ |
error: |
loader_abort(ldr); |
free(ldr); |
return 0; |
} |
int task_wait(task_id_t id, task_exit_t *texit, int *retval) |
{ |
ipcarg_t te, rv; |
int rc; |
rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id), |
UPPER32(id), &te, &rv); |
*texit = te; |
*retval = rv; |
return rc; |
} |
int task_retval(int val) |
{ |
return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/libc.c |
---|
27,30 → 27,31 |
*/ |
/** @addtogroup lc Libc |
* @brief HelenOS C library |
* @brief HelenOS C library |
* @{ |
* @} |
*/ |
/** @addtogroup libc generic |
* @ingroup lc |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <libc.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <malloc.h> |
#include <tls.h> |
#include <thread.h> |
#include <fibril.h> |
#include <io/stream.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
void _exit(int status) |
60,29 → 61,33 |
void __main(void *pcb_ptr) |
{ |
fibril_t *f; |
int retval; |
__heap_init(); |
__async_init(); |
fibril_t *fibril = fibril_setup(); |
__tcb_set(fibril->tcb); |
/* Save the PCB pointer */ |
__pcb = (pcb_t *) pcb_ptr; |
int argc; |
char **argv; |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
_async_init(); |
f = fibril_setup(); |
__tcb_set(f->tcb); |
open_console(); |
/* Save the PCB pointer */ |
__pcb = (pcb_t *)pcb_ptr; |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
__stdio_init(0, NULL); |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
__stdio_init(__pcb->filc, __pcb->filv); |
} |
retval = main(argc, argv); |
main(argc, argv); |
__stdio_done(); |
(void) task_retval(retval); |
} |
void __exit(void) |
/branches/arm/uspace/lib/libc/generic/getopt.c |
---|
47,7 → 47,7 |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
const char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
162,7 → 162,7 |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
const char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
241,7 → 241,7 |
} |
} |
if ((optchar = (int)*place++) == (int)':' || |
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
(oli = str_chr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
/* option letter unknown or ':' */ |
if (!*place) |
++optind; |
275,7 → 275,7 |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
optarg = place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
353,7 → 353,8 |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
char *current_argv; |
const char *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
377,20 → 378,20 |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
if ((has_equal = str_chr(current_argv, '=')) != NULL) { |
/* argument found (--option=arg) */ |
current_argv_len = has_equal - current_argv; |
has_equal++; |
} else |
current_argv_len = strlen(current_argv); |
current_argv_len = str_size(current_argv); |
for (i = 0; long_options[i].name; i++) { |
/* find matching long option */ |
if (strncmp(current_argv, long_options[i].name, |
current_argv_len)) |
if (str_lcmp(current_argv, long_options[i].name, |
str_nlength(current_argv, current_argv_len))) |
continue; |
if (strlen(long_options[i].name) == |
if (str_size(long_options[i].name) == |
(unsigned)current_argv_len) { |
/* exact match */ |
match = i; |
/branches/arm/uspace/lib/libc/generic/as.c |
---|
30,7 → 30,7 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <as.h> |
#include <libc.h> |
38,23 → 38,23 |
#include <align.h> |
#include <sys/types.h> |
#include <bitops.h> |
#include <malloc.h> |
/** |
* Either 4*256M on 32-bit architecures or 16*256M on 64-bit architectures. |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t)<<28) |
/** Last position allocated by as_get_mappable_page */ |
static uintptr_t last_allocated = 0; |
/** Create address space area. |
* |
* @param address Virtual address where to place new address space area. |
* @param size Size of the area. |
* @param flags Flags describing type of the area. |
* @param size Size of the area. |
* @param flags Flags describing type of the area. |
* |
* @return address on success, (void *) -1 otherwise. |
* |
*/ |
void *as_area_create(void *address, size_t size, int flags) |
{ |
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t ) address, |
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t) address, |
(sysarg_t) size, (sysarg_t) flags); |
} |
61,15 → 61,16 |
/** Resize address space area. |
* |
* @param address Virtual address pointing into already existing address space |
* area. |
* @param size New requested size of the area. |
* @param flags Currently unused. |
* area. |
* @param size New requested size of the area. |
* @param flags Currently unused. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_resize(void *address, size_t size, int flags) |
{ |
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t ) address, |
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t) address, |
(sysarg_t) size, (sysarg_t) flags); |
} |
76,22 → 77,24 |
/** Destroy address space area. |
* |
* @param address Virtual address pointing into the address space area being |
* destroyed. |
* destroyed. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_destroy(void *address) |
{ |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address); |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t) address); |
} |
/** Change address-space area flags. |
* |
* @param address Virtual address pointing into the address space area being |
* modified. |
* @param flags New flags describing type of the area. |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
99,101 → 102,29 |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
static void * last_allocated = 0; |
/* Start of heap linker symbol */ |
extern char _heap; |
/** Sbrk emulation |
* |
* @param incr New area that should be allocated or negative, |
if it should be shrinked |
* @return Pointer to newly allocated area |
*/ |
void *sbrk(ssize_t incr) |
{ |
int rc; |
void *res; |
/* Check for invalid values */ |
if (incr < 0 && -incr > heapsize) |
return NULL; |
/* Check for too large value */ |
if (incr > 0 && incr+heapsize < heapsize) |
return NULL; |
/* Check for too small values */ |
if (incr < 0 && incr+heapsize > heapsize) |
return NULL; |
/* Check for user limit */ |
if ((maxheapsize != (size_t) (-1)) && (heapsize + incr) > maxheapsize) |
return NULL; |
rc = as_area_resize(&_heap, heapsize + incr, 0); |
if (rc != 0) |
return NULL; |
/* Compute start of new area */ |
res = (void *) &_heap + heapsize; |
heapsize += incr; |
return res; |
} |
/** Set maximum heap size and return pointer just after the heap */ |
void *set_maxheapsize(size_t mhs) |
{ |
maxheapsize = mhs; |
/* Return pointer to area not managed by sbrk */ |
return ((void *) &_heap + maxheapsize); |
} |
/** Return pointer to some unmapped area, where fits new as_area |
* |
* @param sz Requested size of the allocation. |
* @param size Requested size of the allocation. |
* |
* @return Pointer to the beginning |
* @return pointer to the beginning |
* |
* TODO: make some first_fit/... algorithm, we are now just incrementing |
* the pointer to last area |
*/ |
void *as_get_mappable_page(size_t sz) |
void *as_get_mappable_page(size_t size) |
{ |
void *res; |
uint64_t asz; |
int i; |
if (size == 0) |
return NULL; |
if (!sz) |
return NULL; |
asz = 1 << (fnzb64(sz - 1) + 1); |
/* Set heapsize to some meaningful value */ |
if (maxheapsize == -1) |
set_maxheapsize(MAX_HEAP_SIZE); |
size_t sz = 1 << (fnzb(size - 1) + 1); |
if (last_allocated == 0) |
last_allocated = get_max_heap_addr(); |
/* |
* Make sure we allocate from naturally aligned address. |
*/ |
i = 0; |
if (!last_allocated) { |
last_allocated = (void *) ALIGN_UP((void *) &_heap + |
maxheapsize, asz); |
} else { |
last_allocated = (void *) ALIGN_UP(((uintptr_t) |
last_allocated) + (int) (i > 0), asz); |
} |
res = last_allocated; |
last_allocated += ALIGN_UP(sz, PAGE_SIZE); |
return res; |
uintptr_t res = ALIGN_UP(last_allocated, sz); |
last_allocated = res + ALIGN_UP(size, PAGE_SIZE); |
return ((void *) res); |
} |
/** @} |
/branches/arm/uspace/lib/libc/generic/async.c |
---|
30,64 → 30,65 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
/** |
* Asynchronous library |
* |
* The aim of this library is facilitating writing programs utilizing the |
* asynchronous nature of HelenOS IPC, yet using a normal way of programming. |
* The aim of this library is to provide a facility for writing programs which |
* utilize the asynchronous nature of HelenOS IPC, yet using a normal way of |
* programming. |
* |
* You should be able to write very simple multithreaded programs, the async |
* framework will automatically take care of most synchronization problems. |
* |
* Default semantics: |
* - async_send_*(): send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* - async_send_*(): Send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* |
* Example of use (pseudo C): |
* |
* |
* 1) Multithreaded client application |
* |
* fibril_create(fibril1, ...); |
* fibril_create(fibril2, ...); |
* ... |
* |
* int fibril1(void *arg) |
* { |
* conn = ipc_connect_me_to(); |
* c1 = async_send(conn); |
* c2 = async_send(conn); |
* async_wait_for(c1); |
* async_wait_for(c2); |
* ... |
* } |
* fibril_create(fibril1, ...); |
* fibril_create(fibril2, ...); |
* ... |
* |
* int fibril1(void *arg) |
* { |
* conn = ipc_connect_me_to(); |
* c1 = async_send(conn); |
* c2 = async_send(conn); |
* async_wait_for(c1); |
* async_wait_for(c2); |
* ... |
* } |
* |
* |
* 2) Multithreaded server application |
* main() |
* { |
* async_manager(); |
* } |
* |
* |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
* ipc_answer_0(icallid, ELIMIT); |
* return; |
* } |
* ipc_answer_0(icallid, EOK); |
* main() |
* { |
* async_manager(); |
* } |
* |
* callid = async_get_call(&call); |
* handle_call(callid, call); |
* ipc_answer_2(callid, 1, 2, 3); |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
* ipc_answer_0(icallid, ELIMIT); |
* return; |
* } |
* ipc_answer_0(icallid, EOK); |
* |
* callid = async_get_call(&call); |
* .... |
* } |
* callid = async_get_call(&call); |
* handle_call(callid, call); |
* ipc_answer_2(callid, 1, 2, 3); |
* |
* callid = async_get_call(&call); |
* ... |
* } |
* |
*/ |
#include <futex.h> |
94,8 → 95,8 |
#include <async.h> |
#include <fibril.h> |
#include <stdio.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <ipc/ipc.h> |
#include <assert.h> |
#include <errno.h> |
104,24 → 105,26 |
#include <bool.h> |
atomic_t async_futex = FUTEX_INITIALIZER; |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
/** Structures of this type represent a waiting fibril. */ |
typedef struct { |
/** Expiration time. */ |
struct timeval expires; |
struct timeval expires; |
/** If true, this struct is in the timeout list. */ |
int inlist; |
bool inlist; |
/** Timeout list link. */ |
link_t link; |
/** Identification of and link to the waiting fibril. */ |
fid_t fid; |
/** If true, this fibril is currently active. */ |
int active; |
bool active; |
/** If true, we have timed out. */ |
int timedout; |
bool timedout; |
} awaiter_t; |
typedef struct { |
128,10 → 131,11 |
awaiter_t wdata; |
/** If reply was received. */ |
int done; |
bool done; |
/** Pointer to where the answer data is stored. */ |
ipc_call_t *dataptr; |
ipc_call_t *dataptr; |
ipcarg_t retval; |
} amsg_t; |
147,37 → 151,31 |
typedef struct { |
awaiter_t wdata; |
/** Hash table link. */ |
link_t link; |
/** Incoming phone hash. */ |
ipcarg_t in_phone_hash; |
ipcarg_t in_phone_hash; |
/** Messages that should be delivered to this fibril. */ |
link_t msg_queue; |
link_t msg_queue; |
/** Identification of the opening call. */ |
ipc_callid_t callid; |
/** Call data of the opening call. */ |
ipc_call_t call; |
/** Identification of the closing call. */ |
ipc_callid_t close_callid; |
/** Fibril function that will be used to handle the connection. */ |
void (*cfibril)(ipc_callid_t, ipc_call_t *); |
} connection_t; |
/** Identifier of the incoming connection handled by the current fibril. */ |
__thread connection_t *FIBRIL_connection; |
fibril_local connection_t *FIBRIL_connection; |
/** |
* If true, it is forbidden to use async_req functions and all preemption is |
* disabled. |
*/ |
__thread int _in_interrupt_handler; |
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
185,6 → 183,7 |
* Pointer to a fibril function that will be used to handle connections. |
*/ |
static async_client_conn_t client_connection = default_client_connection; |
/** |
* Pointer to a fibril function that will be used to handle interrupt |
* notifications. |
191,46 → 190,37 |
*/ |
static async_client_conn_t interrupt_received = default_interrupt_received; |
/* |
* Getter for _in_interrupt_handler. We need to export the value of this thread |
* local variable to other modules, but the binutils 2.18 linkers die on an |
* attempt to export this symbol in the header file. For now, consider this as a |
* workaround. |
*/ |
bool in_interrupt_handler(void) |
{ |
return _in_interrupt_handler; |
} |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
#define CONN_HASH_TABLE_CHAINS 32 |
#define CONN_HASH_TABLE_CHAINS 32 |
/** Compute hash into the connection hash table based on the source phone hash. |
* |
* @param key Pointer to source phone hash. |
* @param key Pointer to source phone hash. |
* |
* @return Index into the connection hash table. |
* @return Index into the connection hash table. |
* |
*/ |
static hash_index_t conn_hash(unsigned long *key) |
{ |
assert(key); |
return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS); |
} |
/** Compare hash table item with a key. |
* |
* @param key Array containing the source phone hash as the only item. |
* @param keys Expected 1 but ignored. |
* @param item Connection hash table item. |
* @param key Array containing the source phone hash as the only item. |
* @param keys Expected 1 but ignored. |
* @param item Connection hash table item. |
* |
* @return True on match, false otherwise. |
* @return True on match, false otherwise. |
* |
*/ |
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
connection_t *hs; |
hs = hash_table_get_instance(item, connection_t, link); |
return key[0] == hs->in_phone_hash; |
connection_t *hs = hash_table_get_instance(item, connection_t, link); |
return (key[0] == hs->in_phone_hash); |
} |
/** Connection hash table removal callback function. |
238,7 → 228,8 |
* This function is called whenever a connection is removed from the connection |
* hash table. |
* |
* @param item Connection hash table item being removed. |
* @param item Connection hash table item being removed. |
* |
*/ |
static void conn_remove(link_t *item) |
{ |
255,23 → 246,24 |
/** Sort in current fibril's timeout request. |
* |
* @param wd Wait data of the current fibril. |
* @param wd Wait data of the current fibril. |
* |
*/ |
static void insert_timeout(awaiter_t *wd) |
{ |
link_t *tmp; |
awaiter_t *cur; |
wd->timedout = 0; |
wd->inlist = 1; |
tmp = timeout_list.next; |
wd->timedout = false; |
wd->inlist = true; |
link_t *tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
cur = list_get_instance(tmp, awaiter_t, link); |
awaiter_t *cur = list_get_instance(tmp, awaiter_t, link); |
if (tv_gteq(&cur->expires, &wd->expires)) |
break; |
tmp = tmp->next; |
} |
list_append(&wd->link, tmp); |
} |
281,93 → 273,146 |
* its message queue. If the fibril was not active, it is activated and all |
* timeouts are unregistered. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return Zero if the call doesn't match any connection. |
* One if the call was passed to the respective connection |
* fibril. |
* @return False if the call doesn't match any connection. |
* True if the call was passed to the respective connection fibril. |
* |
*/ |
static int route_call(ipc_callid_t callid, ipc_call_t *call) |
static bool route_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
connection_t *conn; |
msg_t *msg; |
link_t *hlp; |
unsigned long key; |
futex_down(&async_futex); |
key = call->in_phone_hash; |
hlp = hash_table_find(&conn_hash_table, &key); |
unsigned long key = call->in_phone_hash; |
link_t *hlp = hash_table_find(&conn_hash_table, &key); |
if (!hlp) { |
futex_up(&async_futex); |
return 0; |
return false; |
} |
conn = hash_table_get_instance(hlp, connection_t, link); |
msg = malloc(sizeof(*msg)); |
connection_t *conn = hash_table_get_instance(hlp, connection_t, link); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
list_append(&msg->link, &conn->msg_queue); |
if (IPC_GET_METHOD(*call) == IPC_M_PHONE_HUNGUP) |
conn->close_callid = callid; |
/* If the connection fibril is waiting for an event, activate it */ |
if (!conn->wdata.active) { |
/* If in timeout list, remove it */ |
if (conn->wdata.inlist) { |
conn->wdata.inlist = 0; |
conn->wdata.inlist = false; |
list_remove(&conn->wdata.link); |
} |
conn->wdata.active = 1; |
conn->wdata.active = true; |
fibril_add_ready(conn->wdata.fid); |
} |
futex_up(&async_futex); |
return true; |
} |
return 1; |
/** Notification fibril. |
* |
* When a notification arrives, a fibril with this implementing function is |
* created. It calls interrupt_received() and does the final cleanup. |
* |
* @param arg Message structure pointer. |
* |
* @return Always zero. |
* |
*/ |
static int notification_fibril(void *arg) |
{ |
msg_t *msg = (msg_t *) arg; |
interrupt_received(msg->callid, &msg->call); |
free(msg); |
return 0; |
} |
/** Process interrupt notification. |
* |
* A new fibril is created which would process the notification. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return False if an error occured. |
* True if the call was passed to the notification fibril. |
* |
*/ |
static bool process_notification(ipc_callid_t callid, ipc_call_t *call) |
{ |
futex_down(&async_futex); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
fid_t fid = fibril_create(notification_fibril, msg); |
fibril_add_ready(fid); |
futex_up(&async_futex); |
return true; |
} |
/** Return new incoming message for the current (fibril-local) connection. |
* |
* @param call Storage where the incoming call data will be stored. |
* @param usecs Timeout in microseconds. Zero denotes no timeout. |
* @param call Storage where the incoming call data will be stored. |
* @param usecs Timeout in microseconds. Zero denotes no timeout. |
* |
* @return If no timeout was specified, then a hash of the |
* incoming call is returned. If a timeout is specified, |
* then a hash of the incoming call is returned unless |
* the timeout expires prior to receiving a message. In |
* that case zero is returned. |
* @return If no timeout was specified, then a hash of the |
* incoming call is returned. If a timeout is specified, |
* then a hash of the incoming call is returned unless |
* the timeout expires prior to receiving a message. In |
* that case zero is returned. |
* |
*/ |
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
{ |
msg_t *msg; |
ipc_callid_t callid; |
connection_t *conn; |
assert(FIBRIL_connection); |
assert(FIBRIL_connection); |
/* GCC 4.1.0 coughs on FIBRIL_connection-> dereference, |
/* Why doing this? |
* GCC 4.1.0 coughs on FIBRIL_connection-> dereference. |
* GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. |
* I would never expect to find so many errors in |
* a compiler *($&$(*&$ |
* I would never expect to find so many errors in |
* a compiler. |
*/ |
conn = FIBRIL_connection; |
connection_t *conn = FIBRIL_connection; |
futex_down(&async_futex); |
if (usecs) { |
gettimeofday(&conn->wdata.expires, NULL); |
tv_add(&conn->wdata.expires, usecs); |
} else { |
conn->wdata.inlist = 0; |
} |
} else |
conn->wdata.inlist = false; |
/* If nothing in queue, wait until something arrives */ |
while (list_empty(&conn->msg_queue)) { |
if (usecs) |
insert_timeout(&conn->wdata); |
conn->wdata.active = 0; |
conn->wdata.active = false; |
/* |
* Note: the current fibril will be rescheduled either due to a |
* timeout or due to an arriving message destined to it. In the |
375,13 → 420,14 |
* case, route_call() will perform the wakeup. |
*/ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* |
* Futex is up after getting back from async_manager get it |
* again. |
* Futex is up after getting back from async_manager. |
* Get it again. |
*/ |
futex_down(&async_futex); |
if (usecs && conn->wdata.timedout && |
list_empty(&conn->msg_queue)) { |
if ((usecs) && (conn->wdata.timedout) |
&& (list_empty(&conn->msg_queue))) { |
/* If we timed out -> exit */ |
futex_up(&async_futex); |
return 0; |
388,9 → 434,10 |
} |
} |
msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
list_remove(&msg->link); |
callid = msg->callid; |
ipc_callid_t callid = msg->callid; |
*call = msg->call; |
free(msg); |
402,8 → 449,9 |
* |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
{ |
412,8 → 460,11 |
/** Default fibril function that gets called to handle interrupt notifications. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
424,17 → 475,17 |
* When a new connection arrives, a fibril with this implementing function is |
* created. It calls client_connection() and does the final cleanup. |
* |
* @param arg Connection structure pointer. |
* @param arg Connection structure pointer. |
* |
* @return Always zero. |
* @return Always zero. |
* |
*/ |
static int connection_fibril(void *arg) |
static int connection_fibril(void *arg) |
{ |
unsigned long key; |
msg_t *msg; |
int close_answered = 0; |
/* Setup fibril-local connection pointer */ |
/* |
* Setup fibril-local connection pointer and call client_connection(). |
* |
*/ |
FIBRIL_connection = (connection_t *) arg; |
FIBRIL_connection->cfibril(FIBRIL_connection->callid, |
&FIBRIL_connection->call); |
441,20 → 492,21 |
/* Remove myself from the connection hash table */ |
futex_down(&async_futex); |
key = FIBRIL_connection->in_phone_hash; |
unsigned long key = FIBRIL_connection->in_phone_hash; |
hash_table_remove(&conn_hash_table, &key, 1); |
futex_up(&async_futex); |
/* Answer all remaining messages with EHANGUP */ |
while (!list_empty(&FIBRIL_connection->msg_queue)) { |
msg_t *msg; |
msg = list_get_instance(FIBRIL_connection->msg_queue.next, |
msg_t, link); |
list_remove(&msg->link); |
if (msg->callid == FIBRIL_connection->close_callid) |
close_answered = 1; |
ipc_answer_0(msg->callid, EHANGUP); |
free(msg); |
} |
if (FIBRIL_connection->close_callid) |
ipc_answer_0(FIBRIL_connection->close_callid, EOK); |
463,43 → 515,45 |
/** Create a new fibril for a new connection. |
* |
* Creates new fibril for connection, fills in connection structures and inserts |
* Create new fibril for connection, fill in connection structures and inserts |
* it into the hash table, so that later we can easily do routing of messages to |
* particular fibrils. |
* |
* @param in_phone_hash Identification of the incoming connection. |
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. |
* If callid is zero, the connection was opened by |
* accepting the IPC_M_CONNECT_TO_ME call and this function |
* is called directly by the server. |
* @param call Call data of the opening call. |
* @param cfibril Fibril function that should be called upon opening the |
* connection. |
* @param in_phone_hash Identification of the incoming connection. |
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. |
* If callid is zero, the connection was opened by |
* accepting the IPC_M_CONNECT_TO_ME call and this function |
* is called directly by the server. |
* @param call Call data of the opening call. |
* @param cfibril Fibril function that should be called upon opening the |
* connection. |
* |
* @return New fibril id or NULL on failure. |
* @return New fibril id or NULL on failure. |
* |
*/ |
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) |
{ |
connection_t *conn; |
unsigned long key; |
conn = malloc(sizeof(*conn)); |
connection_t *conn = malloc(sizeof(*conn)); |
if (!conn) { |
if (callid) |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
conn->in_phone_hash = in_phone_hash; |
list_initialize(&conn->msg_queue); |
conn->callid = callid; |
conn->close_callid = 0; |
conn->close_callid = false; |
if (call) |
conn->call = *call; |
conn->wdata.active = 1; /* We will activate the fibril ASAP */ |
/* We will activate the fibril ASAP */ |
conn->wdata.active = true; |
conn->cfibril = cfibril; |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
if (callid) |
506,14 → 560,16 |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
/* Add connection to the connection hash table */ |
key = conn->in_phone_hash; |
unsigned long key = conn->in_phone_hash; |
futex_down(&async_futex); |
hash_table_insert(&conn_hash_table, &key, &conn->link); |
futex_up(&async_futex); |
fibril_add_ready(conn->wdata.fid); |
return conn->wdata.fid; |
} |
522,33 → 578,37 |
* If the call has the IPC_M_CONNECT_ME_TO method, a new connection is created. |
* Otherwise the call is routed to its connection fibril. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
/* Unrouted call - do some default behaviour */ |
if ((callid & IPC_CALLID_NOTIFICATION)) { |
_in_interrupt_handler = 1; |
(*interrupt_received)(callid, call); |
_in_interrupt_handler = 0; |
return; |
} |
process_notification(callid, call); |
goto out; |
} |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_CONNECT_ME: |
case IPC_M_CONNECT_ME_TO: |
/* Open new connection with fibril etc. */ |
async_new_connection(IPC_GET_ARG5(*call), callid, call, |
client_connection); |
return; |
goto out; |
} |
/* Try to route the call through the connection hash table */ |
if (route_call(callid, call)) |
return; |
goto out; |
/* Unknown call from unknown phone - hang it up */ |
ipc_answer_0(callid, EHANGUP); |
return; |
out: |
; |
} |
/** Fire all timeouts that expired. */ |
555,47 → 615,44 |
static void handle_expired_timeouts(void) |
{ |
struct timeval tv; |
awaiter_t *waiter; |
link_t *cur; |
gettimeofday(&tv, NULL); |
futex_down(&async_futex); |
cur = timeout_list.next; |
link_t *cur = timeout_list.next; |
while (cur != &timeout_list) { |
waiter = list_get_instance(cur, awaiter_t, link); |
awaiter_t *waiter = list_get_instance(cur, awaiter_t, link); |
if (tv_gt(&waiter->expires, &tv)) |
break; |
cur = cur->next; |
list_remove(&waiter->link); |
waiter->inlist = 0; |
waiter->timedout = 1; |
waiter->inlist = false; |
waiter->timedout = true; |
/* |
* Redundant condition? |
* The fibril should not be active when it gets here. |
* Redundant condition? |
* The fibril should not be active when it gets here. |
*/ |
if (!waiter->active) { |
waiter->active = 1; |
waiter->active = true; |
fibril_add_ready(waiter->fid); |
} |
} |
futex_up(&async_futex); |
} |
/** Endless loop dispatching incoming calls and answers. |
* |
* @return Never returns. |
* @return Never returns. |
* |
*/ |
static int async_manager_worker(void) |
{ |
ipc_call_t call; |
ipc_callid_t callid; |
int timeout; |
awaiter_t *waiter; |
struct timeval tv; |
while (1) { |
while (true) { |
if (fibril_switch(FIBRIL_FROM_MANAGER)) { |
futex_up(&async_futex); |
/* |
604,11 → 661,17 |
*/ |
continue; |
} |
futex_down(&async_futex); |
suseconds_t timeout; |
if (!list_empty(&timeout_list)) { |
waiter = list_get_instance(timeout_list.next, awaiter_t, |
link); |
awaiter_t *waiter = list_get_instance(timeout_list.next, |
awaiter_t, link); |
struct timeval tv; |
gettimeofday(&tv, NULL); |
if (tv_gteq(&tv, &waiter->expires)) { |
futex_up(&async_futex); |
handle_expired_timeouts(); |
617,19 → 680,21 |
timeout = tv_sub(&waiter->expires, &tv); |
} else |
timeout = SYNCH_NO_TIMEOUT; |
futex_up(&async_futex); |
callid = ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
ipc_call_t call; |
ipc_callid_t callid = ipc_wait_cycle(&call, timeout, |
SYNCH_FLAGS_NONE); |
if (!callid) { |
handle_expired_timeouts(); |
continue; |
} |
if (callid & IPC_CALLID_ANSWERED) { |
if (callid & IPC_CALLID_ANSWERED) |
continue; |
} |
handle_call(callid, &call); |
} |
637,16 → 702,17 |
} |
/** Function to start async_manager as a standalone fibril. |
* |
* |
* When more kernel threads are used, one async manager should exist per thread. |
* |
* @param arg Unused. |
* @param arg Unused. |
* @return Never returns. |
* |
* @return Never returns. |
*/ |
static int async_manager_fibril(void *arg) |
{ |
futex_up(&async_futex); |
/* |
* async_futex is always locked when entering manager |
*/ |
658,9 → 724,7 |
/** Add one manager to manager list. */ |
void async_create_manager(void) |
{ |
fid_t fid; |
fid = fibril_create(async_manager_fibril, NULL); |
fid_t fid = fibril_create(async_manager_fibril, NULL); |
fibril_add_manager(fid); |
} |
672,9 → 736,9 |
/** Initialize the async framework. |
* |
* @return Zero on success or an error code. |
* @return Zero on success or an error code. |
*/ |
int _async_init(void) |
int __async_init(void) |
{ |
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, |
&conn_hash_table_ops)) { |
692,30 → 756,33 |
* |
* Notify the fibril which is waiting for this message that it has arrived. |
* |
* @param private Pointer to the asynchronous message record. |
* @param retval Value returned in the answer. |
* @param data Call data of the answer. |
* @param arg Pointer to the asynchronous message record. |
* @param retval Value returned in the answer. |
* @param data Call data of the answer. |
*/ |
static void reply_received(void *private, int retval, ipc_call_t *data) |
static void reply_received(void *arg, int retval, ipc_call_t *data) |
{ |
amsg_t *msg = (amsg_t *) private; |
futex_down(&async_futex); |
amsg_t *msg = (amsg_t *) arg; |
msg->retval = retval; |
futex_down(&async_futex); |
/* Copy data after futex_down, just in case the call was detached */ |
if (msg->dataptr) |
*msg->dataptr = *data; |
if ((msg->dataptr) && (data)) |
*msg->dataptr = *data; |
write_barrier(); |
/* Remove message from timeout list */ |
if (msg->wdata.inlist) |
list_remove(&msg->wdata.link); |
msg->done = 1; |
msg->done = true; |
if (!msg->wdata.active) { |
msg->wdata.active = 1; |
msg->wdata.active = true; |
fibril_add_ready(msg->wdata.fid); |
} |
futex_up(&async_futex); |
} |
724,38 → 791,36 |
* The return value can be used as input for async_wait() to wait for |
* completion. |
* |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
amsg_t *msg = malloc(sizeof(*msg)); |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
msg->wdata.inlist = false; |
/* We may sleep in the next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
reply_received, 1); |
reply_received, true); |
return (aid_t) msg; |
} |
764,113 → 829,119 |
* The return value can be used as input for async_wait() to wait for |
* completion. |
* |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
amsg_t *msg = malloc(sizeof(*msg)); |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
msg->wdata.inlist = false; |
/* We may sleep in next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
reply_received, 1); |
reply_received, true); |
return (aid_t) msg; |
} |
/** Wait for a message sent by the async framework. |
* |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* |
*/ |
void async_wait_for(aid_t amsgid, ipcarg_t *retval) |
{ |
amsg_t *msg = (amsg_t *) amsgid; |
futex_down(&async_futex); |
if (msg->done) { |
futex_up(&async_futex); |
goto done; |
} |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.inlist = 0; |
msg->wdata.active = false; |
msg->wdata.inlist = false; |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
} |
/** Wait for a message sent by the async framework, timeout variant. |
* |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param timeout Timeout in microseconds. |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param timeout Timeout in microseconds. |
* |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* |
*/ |
int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout) |
{ |
amsg_t *msg = (amsg_t *) amsgid; |
/* TODO: Let it go through the event read at least once */ |
if (timeout < 0) |
return ETIMEOUT; |
futex_down(&async_futex); |
if (msg->done) { |
futex_up(&async_futex); |
goto done; |
} |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
if (!msg->done) |
return ETIMEOUT; |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
return 0; |
} |
878,38 → 949,38 |
* |
* The current fibril is suspended but the thread continues to execute. |
* |
* @param timeout Duration of the wait in microseconds. |
* @param timeout Duration of the wait in microseconds. |
* |
*/ |
void async_usleep(suseconds_t timeout) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
if (_in_interrupt_handler) { |
printf("Cannot call async_usleep in interrupt handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
if (!msg) |
return; |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
futex_down(&async_futex); |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch()...*/ |
/* Futex is up automatically after fibril_switch() */ |
free(msg); |
} |
/** Setter for client_connection function pointer. |
* |
* @param conn Function that will implement a new connection fibril. |
* @param conn Function that will implement a new connection fibril. |
* |
*/ |
void async_set_client_connection(async_client_conn_t conn) |
{ |
918,12 → 989,12 |
/** Setter for interrupt_received function pointer. |
* |
* @param conn Function that will implement a new interrupt |
* notification fibril. |
* @param intr Function that will implement a new interrupt |
* notification fibril. |
*/ |
void async_set_interrupt_received(async_client_conn_t conn) |
void async_set_interrupt_received(async_client_conn_t intr) |
{ |
interrupt_received = conn; |
interrupt_received = intr; |
} |
/** Pseudo-synchronous message sending - fast version. |
933,18 → 1004,20 |
* This function can only transfer 4 register payload arguments. For |
* transferring more arguments, see the slower async_req_slow(). |
* |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* @return Return code of the reply or a negative error code. |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2, |
951,21 → 1024,27 |
ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
973,19 → 1052,21 |
* |
* Send message asynchronously and return only after the reply arrives. |
* |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* @return Return code of the reply or a negative error code. |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1, |
992,21 → 1073,27 |
ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
/branches/arm/uspace/lib/libc/generic/errno.c |
---|
0,0 → 1,41 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <errno.h> |
#include <fibril.h> |
int _errno; |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/mman.c |
---|
37,17 → 37,18 |
#include <as.h> |
#include <unistd.h> |
void *mmap(void *start, size_t length, int prot, int flags, int fd, |
void *mmap(void *start, size_t length, int prot, int flags, int fd, |
off_t offset) |
{ |
if (!start) |
start = as_get_mappable_page(length); |
// if (! ((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE))) |
// if (!((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE))) |
// return MAP_FAILED; |
if (! (flags & MAP_ANONYMOUS)) |
if (!(flags & MAP_ANONYMOUS)) |
return MAP_FAILED; |
return as_area_create(start, length, prot); |
} |
/branches/arm/uspace/lib/libc/generic/devmap.c |
---|
0,0 → 1,289 |
/* |
* Copyright (c) 2007 Josef Cejka |
* Copyright (c) 2009 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 <string.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <devmap.h> |
#include <async.h> |
#include <errno.h> |
static int devmap_phone_driver = -1; |
static int devmap_phone_client = -1; |
/** Get phone to device mapper task. */ |
int devmap_get_phone(devmap_interface_t iface, unsigned int flags) |
{ |
switch (iface) { |
case DEVMAP_DRIVER: |
if (devmap_phone_driver >= 0) |
return devmap_phone_driver; |
if (flags & IPC_FLAG_BLOCKING) |
devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
else |
devmap_phone_driver = ipc_connect_me_to(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
return devmap_phone_driver; |
case DEVMAP_CLIENT: |
if (devmap_phone_client >= 0) |
return devmap_phone_client; |
if (flags & IPC_FLAG_BLOCKING) |
devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
else |
devmap_phone_client = ipc_connect_me_to(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
return devmap_phone_client; |
default: |
return -1; |
} |
} |
void devmap_hangup_phone(devmap_interface_t iface) |
{ |
switch (iface) { |
case DEVMAP_DRIVER: |
if (devmap_phone_driver >= 0) { |
ipc_hangup(devmap_phone_driver); |
devmap_phone_driver = -1; |
} |
break; |
case DEVMAP_CLIENT: |
if (devmap_phone_client >= 0) { |
ipc_hangup(devmap_phone_client); |
devmap_phone_client = -1; |
} |
break; |
default: |
break; |
} |
} |
/** Register new driver with devmap. */ |
int devmap_driver_register(const char *name, async_client_conn_t conn) |
{ |
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return -1; |
} |
async_set_client_connection(conn); |
ipcarg_t callback_phonehash; |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
async_serialize_end(); |
return retval; |
} |
/** Register new device. |
* |
* @param name Device name. |
* @param handle Output: Handle to the created instance of device. |
* |
*/ |
int devmap_device_register(const char *name, dev_handle_t *handle) |
{ |
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return retval; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
return retval; |
} |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
return retval; |
} |
int devmap_device_get_handle(const char *name, dev_handle_t *handle, unsigned int flags) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, flags); |
if (phone < 0) |
return phone; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return retval; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) -1; |
return retval; |
} |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
return retval; |
} |
int devmap_device_connect(dev_handle_t handle, unsigned int flags) |
{ |
int phone; |
if (flags & IPC_FLAG_BLOCKING) { |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, handle); |
} else { |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, handle); |
} |
return phone; |
} |
int devmap_null_create(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return -1; |
ipcarg_t null_id; |
int retval = async_req_0_1(phone, DEVMAP_DEVICE_NULL_CREATE, &null_id); |
if (retval != EOK) |
return -1; |
return (int) null_id; |
} |
void devmap_null_destroy(int null_id) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return; |
async_req_1_0(phone, DEVMAP_DEVICE_NULL_DESTROY, (ipcarg_t) null_id); |
} |
ipcarg_t devmap_device_get_count(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return 0; |
ipcarg_t count; |
int retval = async_req_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count); |
if (retval != EOK) |
return 0; |
return count; |
} |
ipcarg_t devmap_device_get_devices(ipcarg_t count, dev_desc_t *data) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return 0; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer); |
ipcarg_t retval = ipc_data_read_start(phone, data, count * sizeof(dev_desc_t)); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return 0; |
} |
async_wait_for(req, &retval); |
async_serialize_end(); |
if (retval != EOK) |
return 0; |
return IPC_GET_ARG1(answer); |
} |
/branches/arm/uspace/lib/libc/generic/vfs/vfs.c |
---|
31,7 → 31,7 |
*/ |
/** @file |
*/ |
#include <vfs/vfs.h> |
#include <vfs/canonify.h> |
#include <stdlib.h> |
38,8 → 38,8 |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <stdio.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
48,16 → 48,17 |
#include <futex.h> |
#include <errno.h> |
#include <string.h> |
#include <devmap.h> |
#include <ipc/vfs.h> |
#include <ipc/devmap.h> |
#include "../../srv/vfs/vfs.h" |
int vfs_phone = -1; |
futex_t vfs_phone_futex = FUTEX_INITIALIZER; |
static int vfs_phone = -1; |
static futex_t vfs_phone_futex = FUTEX_INITIALIZER; |
static futex_t cwd_futex = FUTEX_INITIALIZER; |
futex_t cwd_futex = FUTEX_INITIALIZER; |
DIR *cwd_dir = NULL; |
char *cwd_path = NULL; |
size_t cwd_len = 0; |
size_t cwd_size = 0; |
char *absolutize(const char *path, size_t *retlen) |
{ |
65,22 → 66,22 |
char *ncwd_path_nc; |
futex_down(&cwd_futex); |
size_t len = strlen(path); |
size_t size = str_size(path); |
if (*path != '/') { |
if (!cwd_path) { |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path_nc = malloc(cwd_len + 1 + len + 1); |
ncwd_path_nc = malloc(cwd_size + 1 + size + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(ncwd_path_nc, cwd_path); |
ncwd_path_nc[cwd_len] = '/'; |
ncwd_path_nc[cwd_len + 1] = '\0'; |
str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path); |
ncwd_path_nc[cwd_size] = '/'; |
ncwd_path_nc[cwd_size + 1] = '\0'; |
} else { |
ncwd_path_nc = malloc(len + 1); |
ncwd_path_nc = malloc(size + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
87,7 → 88,7 |
} |
ncwd_path_nc[0] = '\0'; |
} |
strcat(ncwd_path_nc, path); |
str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path); |
ncwd_path = canonify(ncwd_path_nc, retlen); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
99,7 → 100,7 |
* the address in ncwd_path need not be the same as ncwd_path_nc, even |
* though they both point into the same dynamically allocated buffer. |
*/ |
ncwd_path = strdup(ncwd_path); |
ncwd_path = str_dup(ncwd_path); |
free(ncwd_path_nc); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
109,75 → 110,44 |
return ncwd_path; |
} |
static int vfs_connect(void) |
static void vfs_connect(void) |
{ |
if (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
return vfs_phone; |
while (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
} |
static int device_get_handle(char *name, dev_handle_t *handle) |
int mount(const char *fs_name, const char *mp, const char *dev, |
const char *opts, unsigned int flags) |
{ |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, |
0); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
ipc_hangup(phone); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (retval == EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
} |
ipc_hangup(phone); |
return retval; |
} |
int mount(const char *fs_name, const char *mp, const char *dev) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
dev_handle_t dev_handle; |
res = device_get_handle(dev, &dev_handle); |
res = devmap_device_get_handle(dev, &dev_handle, flags); |
if (res != EOK) |
return res; |
size_t mpa_len; |
char *mpa = absolutize(mp, &mpa_len); |
size_t mpa_size; |
char *mpa = absolutize(mp, &mpa_size); |
if (!mpa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return res; |
} |
vfs_connect(); |
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name)); |
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
185,8 → 155,8 |
free(mpa); |
return (int) rc; |
} |
/* Ask VFS whether it likes fs_name. */ |
rc = async_req_0_0(vfs_phone, IPC_M_PING); |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
194,7 → 164,9 |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len); |
/* Ask VFS whether it likes fs_name. */ |
rc = async_req_0_0(vfs_phone, IPC_M_PING); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
202,38 → 174,32 |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
static int _open(const char *path, int lflag, int oflag, ...) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
vfs_connect(); |
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
245,9 → 211,10 |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
256,24 → 223,37 |
return _open(path, L_FILE, oflag); |
} |
int open_node(fdi_node_t *node, int oflag) |
{ |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipc_call_t answer; |
aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle, |
node->dev_handle, node->index, oflag, &answer); |
ipcarg_t rc; |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
int close(int fildes) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
vfs_connect(); |
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
282,7 → 262,6 |
ssize_t read(int fildes, void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
289,15 → 268,9 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
316,7 → 289,6 |
ssize_t write(int fildes, const void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
323,15 → 295,9 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
348,25 → 314,31 |
return -1; |
} |
int fsync(int fildes) |
{ |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
off_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
(ipcarg_t)&newoffs); |
vfs_connect(); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence, |
&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
374,30 → 346,86 |
if (rc != EOK) |
return (off_t) -1; |
return newoffs; |
return (off_t) newoffs; |
} |
int ftruncate(int fildes, off_t length) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
vfs_connect(); |
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
int fstat(int fildes, struct stat *stat) |
{ |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL); |
rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return rc; |
} |
int stat(const char *path, struct stat *stat) |
{ |
ipcarg_t rc; |
aid_t req; |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_IN_STAT, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
} |
DIR *opendir(const char *dirname) |
{ |
DIR *dirp = malloc(sizeof(DIR)); |
433,28 → 461,20 |
int mkdir(const char *path, mode_t mode) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
466,33 → 486,25 |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
return rc; |
} |
static int _unlink(const char *path, int lflag) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
504,7 → 516,7 |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
return rc; |
} |
int unlink(const char *path) |
519,17 → 531,16 |
int rename(const char *old, const char *new) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t olda_len; |
char *olda = absolutize(old, &olda_len); |
size_t olda_size; |
char *olda = absolutize(old, &olda_size); |
if (!olda) |
return ENOMEM; |
size_t newa_len; |
char *newa = absolutize(new, &newa_len); |
size_t newa_size; |
char *newa = absolutize(new, &newa_size); |
if (!newa) { |
free(olda); |
return ENOMEM; |
537,18 → 548,10 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return res; |
} |
} |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_len); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
557,7 → 560,7 |
free(newa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, newa, newa_len); |
rc = ipc_data_write_start(vfs_phone, newa, newa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
576,8 → 579,8 |
int chdir(const char *path) |
{ |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
593,11 → 596,11 |
cwd_dir = NULL; |
free(cwd_path); |
cwd_path = NULL; |
cwd_len = 0; |
cwd_size = 0; |
} |
cwd_dir = d; |
cwd_path = pa; |
cwd_len = pa_len; |
cwd_size = pa_size; |
futex_up(&cwd_futex); |
return EOK; |
} |
607,14 → 610,43 |
if (!size) |
return NULL; |
futex_down(&cwd_futex); |
if (size < cwd_len + 1) { |
if (size < cwd_size + 1) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(buf, cwd_path); |
str_cpy(buf, size, cwd_path); |
futex_up(&cwd_futex); |
return buf; |
} |
int fd_phone(int fildes) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (!stat.devfs_stat.device) |
return -1; |
return devmap_device_connect(stat.devfs_stat.device, 0); |
} |
int fd_node(int fildes, fdi_node_t *node) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (rc == EOK) { |
node->fs_handle = stat.fs_handle; |
node->dev_handle = stat.dev_handle; |
node->index = stat.index; |
} |
return rc; |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/vfs/canonify.c |
---|
36,6 → 36,7 |
*/ |
#include <stdlib.h> |
#include <vfs/canonify.h> |
/** Token types used for tokenization of path. */ |
typedef enum { |
/branches/arm/uspace/lib/libc/generic/fibril_sync.c |
---|
0,0 → 1,219 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <fibril_sync.h> |
#include <fibril.h> |
#include <async.h> |
#include <adt/list.h> |
#include <futex.h> |
#include <assert.h> |
void fibril_mutex_initialize(fibril_mutex_t *fm) |
{ |
fm->counter = 1; |
list_initialize(&fm->waiters); |
} |
void fibril_mutex_lock(fibril_mutex_t *fm) |
{ |
futex_down(&async_futex); |
if (fm->counter-- <= 0) { |
fibril_t *f = (fibril_t *) fibril_get_id(); |
list_append(&f->link, &fm->waiters); |
fibril_switch(FIBRIL_TO_MANAGER); |
} else { |
futex_up(&async_futex); |
} |
} |
bool fibril_mutex_trylock(fibril_mutex_t *fm) |
{ |
bool locked = false; |
futex_down(&async_futex); |
if (fm->counter > 0) { |
fm->counter--; |
locked = true; |
} |
futex_up(&async_futex); |
return locked; |
} |
static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm) |
{ |
assert(fm->counter <= 0); |
if (fm->counter++ < 0) { |
link_t *tmp; |
fibril_t *f; |
assert(!list_empty(&fm->waiters)); |
tmp = fm->waiters.next; |
f = list_get_instance(tmp, fibril_t, link); |
list_remove(&f->link); |
fibril_add_ready((fid_t) f); |
} |
} |
void fibril_mutex_unlock(fibril_mutex_t *fm) |
{ |
futex_down(&async_futex); |
_fibril_mutex_unlock_unsafe(fm); |
futex_up(&async_futex); |
} |
void fibril_rwlock_initialize(fibril_rwlock_t *frw) |
{ |
frw->writers = 0; |
frw->readers = 0; |
list_initialize(&frw->waiters); |
} |
void fibril_rwlock_read_lock(fibril_rwlock_t *frw) |
{ |
futex_down(&async_futex); |
if (frw->writers) { |
fibril_t *f = (fibril_t *) fibril_get_id(); |
f->flags &= ~FIBRIL_WRITER; |
list_append(&f->link, &frw->waiters); |
fibril_switch(FIBRIL_TO_MANAGER); |
} else { |
frw->readers++; |
futex_up(&async_futex); |
} |
} |
void fibril_rwlock_write_lock(fibril_rwlock_t *frw) |
{ |
futex_down(&async_futex); |
if (frw->writers || frw->readers) { |
fibril_t *f = (fibril_t *) fibril_get_id(); |
f->flags |= FIBRIL_WRITER; |
list_append(&f->link, &frw->waiters); |
fibril_switch(FIBRIL_TO_MANAGER); |
} else { |
frw->writers++; |
futex_up(&async_futex); |
} |
} |
static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw) |
{ |
futex_down(&async_futex); |
assert(frw->readers || (frw->writers == 1)); |
if (frw->readers) { |
if (--frw->readers) |
goto out; |
} else { |
frw->writers--; |
} |
assert(!frw->readers && !frw->writers); |
while (!list_empty(&frw->waiters)) { |
link_t *tmp = frw->waiters.next; |
fibril_t *f = list_get_instance(tmp, fibril_t, link); |
if (f->flags & FIBRIL_WRITER) { |
if (frw->readers) |
break; |
list_remove(&f->link); |
fibril_add_ready((fid_t) f); |
frw->writers++; |
break; |
} else { |
list_remove(&f->link); |
fibril_add_ready((fid_t) f); |
frw->readers++; |
} |
} |
out: |
futex_up(&async_futex); |
} |
void fibril_rwlock_read_unlock(fibril_rwlock_t *frw) |
{ |
_fibril_rwlock_common_unlock(frw); |
} |
void fibril_rwlock_write_unlock(fibril_rwlock_t *frw) |
{ |
_fibril_rwlock_common_unlock(frw); |
} |
void fibril_condvar_initialize(fibril_condvar_t *fcv) |
{ |
list_initialize(&fcv->waiters); |
} |
void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm) |
{ |
fibril_t *f = (fibril_t *) fibril_get_id(); |
futex_down(&async_futex); |
list_append(&f->link, &fcv->waiters); |
_fibril_mutex_unlock_unsafe(fm); |
fibril_switch(FIBRIL_TO_MANAGER); |
fibril_mutex_lock(fm); |
} |
static void _fibril_condvar_wakeup_common(fibril_condvar_t *fcv, bool once) |
{ |
link_t *tmp; |
fibril_t *f; |
futex_down(&async_futex); |
while (!list_empty(&fcv->waiters)) { |
tmp = fcv->waiters.next; |
f = list_get_instance(tmp, fibril_t, link); |
list_remove(&f->link); |
fibril_add_ready((fid_t) f); |
if (once) |
break; |
} |
futex_up(&async_futex); |
} |
void fibril_condvar_signal(fibril_condvar_t *fcv) |
{ |
_fibril_condvar_wakeup_common(fcv, true); |
} |
void fibril_condvar_broadcast(fibril_condvar_t *fcv) |
{ |
_fibril_condvar_wakeup_common(fcv, false); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/ipc.c |
---|
43,7 → 43,7 |
#include <libc.h> |
#include <malloc.h> |
#include <errno.h> |
#include <libadt/list.h> |
#include <adt/list.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <futex.h> |
232,7 → 232,7 |
return; |
} |
if (callid == IPC_CALLRET_FATAL) { |
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { |
futex_up(&ipc_futex); |
/* Call asynchronous handler with error code */ |
if (call->callback) |
241,7 → 241,7 |
return; |
} |
if (callid == IPC_CALLRET_TEMPORARY) { |
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { |
futex_up(&ipc_futex); |
call->u.msg.phoneid = phoneid; |
309,7 → 309,7 |
callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, |
arg2, arg3, arg4); |
if (callid == IPC_CALLRET_TEMPORARY) { |
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { |
if (!call) { |
call = ipc_prepare_async(private, callback); |
if (!call) |
442,7 → 442,7 |
call = list_get_instance(queued_calls.next, async_call_t, list); |
callid = _ipc_call_async(call->u.msg.phoneid, |
&call->u.msg.data); |
if (callid == IPC_CALLRET_TEMPORARY) { |
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { |
break; |
} |
list_remove(&call->list); |
451,7 → 451,7 |
if (call->fid) |
fibril_add_ready(call->fid); |
if (callid == IPC_CALLRET_FATAL) { |
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { |
if (call->callback) |
call->callback(call->private, ENOENT, NULL); |
free(call); |
598,7 → 598,7 |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
605,6 → 605,30 |
return newphid; |
} |
/** Ask through phone for a new connection to some service. |
* |
* If the connection is not available at the moment, the |
* call will block. |
* |
* @param phoneid Phone handle used for contacting the other side. |
* @param arg1 User defined argument. |
* @param arg2 User defined argument. |
* @param arg3 User defined argument. |
* |
* @return New phone handle on success or a negative error code. |
*/ |
int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) |
{ |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
return newphid; |
} |
/** Hang up a phone. |
* |
* @param phoneid Handle of the phone to be hung up. |
666,6 → 690,23 |
arg2, mode); |
} |
int ipc_forward_slow(ipc_callid_t callid, int phoneid, int method, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
int mode) |
{ |
ipc_call_t data; |
IPC_SET_METHOD(data, method); |
IPC_SET_ARG1(data, arg1); |
IPC_SET_ARG2(data, arg2); |
IPC_SET_ARG3(data, arg3); |
IPC_SET_ARG4(data, arg4); |
IPC_SET_ARG5(data, arg5); |
return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode); |
} |
/** Wrapper for making IPC_M_SHARE_IN calls. |
* |
* @param phoneid Phone that will be used to contact the receiving side. |
847,7 → 888,7 |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size) |
int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size); |
} |
860,7 → 901,7 |
* |
* @return Zero on success or a negative error code from errno.h. |
*/ |
int ipc_data_write_start(int phoneid, void *src, size_t size) |
int ipc_data_write_start(int phoneid, const void *src, size_t size) |
{ |
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
(ipcarg_t) size); |
/branches/arm/uspace/lib/libc/generic/adt/hash_table.c |
---|
0,0 → 1,196 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
/* |
* This is an implementation of generic chained hash table. |
*/ |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <unistd.h> |
#include <malloc.h> |
#include <assert.h> |
#include <stdio.h> |
#include <string.h> |
/** Create chained hash table. |
* |
* @param h Hash table structure. Will be initialized by this call. |
* @param m Number of hash table buckets. |
* @param max_keys Maximal number of keys needed to identify an item. |
* @param op Hash table operations structure. |
* @return True on success |
*/ |
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, |
hash_table_operations_t *op) |
{ |
hash_count_t i; |
assert(h); |
assert(op && op->hash && op->compare); |
assert(max_keys > 0); |
h->entry = malloc(m * sizeof(link_t)); |
if (!h->entry) { |
printf("cannot allocate memory for hash table\n"); |
return false; |
} |
memset((void *) h->entry, 0, m * sizeof(link_t)); |
for (i = 0; i < m; i++) |
list_initialize(&h->entry[i]); |
h->entries = m; |
h->max_keys = max_keys; |
h->op = op; |
return true; |
} |
/** Destroy a hash table instance. |
* |
* @param h Hash table to be destroyed. |
*/ |
void hash_table_destroy(hash_table_t *h) |
{ |
assert(h); |
assert(h->entry); |
free(h->entry); |
} |
/** Insert item into a hash table. |
* |
* @param h Hash table. |
* @param key Array of all keys necessary to compute hash index. |
* @param item Item to be inserted into the hash table. |
*/ |
void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item) |
{ |
hash_index_t chain; |
assert(item); |
assert(h && h->op && h->op->hash && h->op->compare); |
chain = h->op->hash(key); |
assert(chain < h->entries); |
list_append(item, &h->entry[chain]); |
} |
/** Search hash table for an item matching keys. |
* |
* @param h Hash table. |
* @param key Array of all keys needed to compute hash index. |
* |
* @return Matching item on success, NULL if there is no such item. |
*/ |
link_t *hash_table_find(hash_table_t *h, unsigned long key[]) |
{ |
link_t *cur; |
hash_index_t chain; |
assert(h && h->op && h->op->hash && h->op->compare); |
chain = h->op->hash(key); |
assert(chain < h->entries); |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; |
cur = cur->next) { |
if (h->op->compare(key, h->max_keys, cur)) { |
/* |
* The entry is there. |
*/ |
return cur; |
} |
} |
return NULL; |
} |
/** Remove all matching items from hash table. |
* |
* For each removed item, h->remove_callback() is called. |
* |
* @param h Hash table. |
* @param key Array of keys that will be compared against items of |
* the hash table. |
* @param keys Number of keys in the 'key' array. |
*/ |
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys) |
{ |
hash_index_t chain; |
link_t *cur; |
assert(h && h->op && h->op->hash && h->op->compare && |
h->op->remove_callback); |
assert(keys <= h->max_keys); |
if (keys == h->max_keys) { |
/* |
* All keys are known, hash_table_find() can be used to find the |
* entry. |
*/ |
cur = hash_table_find(h, key); |
if (cur) { |
list_remove(cur); |
h->op->remove_callback(cur); |
} |
return; |
} |
/* |
* Fewer keys were passed. |
* Any partially matching entries are to be removed. |
*/ |
for (chain = 0; chain < h->entries; chain++) { |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; |
cur = cur->next) { |
if (h->op->compare(key, keys, cur)) { |
link_t *hlp; |
hlp = cur; |
cur = cur->prev; |
list_remove(hlp); |
h->op->remove_callback(hlp); |
continue; |
} |
} |
} |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/adt/list.c |
---|
0,0 → 1,112 |
/* |
* Copyright (c) 2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <adt/list.h> |
/** Check for membership |
* |
* Check whether link is contained in the list head. |
* The membership is defined as pointer equivalence. |
* |
* @param link Item to look for. |
* @param head List to look in. |
* |
* @return true if link is contained in head, false otherwise. |
* |
*/ |
int list_member(const link_t *link, const link_t *head) |
{ |
int found = 0; |
link_t *hlp = head->next; |
while (hlp != head) { |
if (hlp == link) { |
found = 1; |
break; |
} |
hlp = hlp->next; |
} |
return found; |
} |
/** Concatenate two lists |
* |
* Concatenate lists head1 and head2, producing a single |
* list head1 containing items from both (in head1, head2 |
* order) and empty list head2. |
* |
* @param head1 First list and concatenated output |
* @param head2 Second list and empty output. |
* |
*/ |
void list_concat(link_t *head1, link_t *head2) |
{ |
if (list_empty(head2)) |
return; |
head2->next->prev = head1->prev; |
head2->prev->next = head1; |
head1->prev->next = head2->next; |
head1->prev = head2->prev; |
list_initialize(head2); |
} |
/** Count list items |
* |
* Return the number of items in the list. |
* |
* @param link List to count. |
* |
* @return Number of items in the list. |
* |
*/ |
unsigned int list_count(const link_t *link) |
{ |
unsigned int count = 0; |
link_t *hlp = link->next; |
while (hlp != link) { |
count++; |
hlp = hlp->next; |
} |
return count; |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/mem.c |
---|
0,0 → 1,239 |
/* |
* Copyright (c) 2005 Martin Decky |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <mem.h> |
#include <stdlib.h> |
#include <sys/types.h> |
/** Fill memory block with a constant value. */ |
void *memset(void *dest, int b, size_t n) |
{ |
char *pb; |
unsigned long *pw; |
size_t word_size; |
size_t n_words; |
unsigned long pattern; |
size_t i; |
size_t fill; |
/* Fill initial segment. */ |
word_size = sizeof(unsigned long); |
fill = word_size - ((uintptr_t) dest & (word_size - 1)); |
if (fill > n) fill = n; |
pb = dest; |
i = fill; |
while (i-- != 0) |
*pb++ = b; |
/* Compute remaining size. */ |
n -= fill; |
if (n == 0) return dest; |
n_words = n / word_size; |
n = n % word_size; |
pw = (unsigned long *) pb; |
/* Create word-sized pattern for aligned segment. */ |
pattern = 0; |
i = word_size; |
while (i-- != 0) |
pattern = (pattern << 8) | (uint8_t) b; |
/* Fill aligned segment. */ |
i = n_words; |
while (i-- != 0) |
*pw++ = pattern; |
pb = (char *) pw; |
/* Fill final segment. */ |
i = n; |
while (i-- != 0) |
*pb++ = b; |
return dest; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
size_t i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
/** Copy memory block. */ |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
size_t i; |
size_t mod, fill; |
size_t word_size; |
size_t n_words; |
const unsigned long *srcw; |
unsigned long *dstw; |
const uint8_t *srcb; |
uint8_t *dstb; |
word_size = sizeof(unsigned long); |
/* |
* Are source and destination addresses congruent modulo word_size? |
* If not, use unaligned_memcpy(). |
*/ |
if (((uintptr_t) dst & (word_size - 1)) != |
((uintptr_t) src & (word_size - 1))) |
return unaligned_memcpy(dst, src, n); |
/* |
* mod is the address modulo word size. fill is the length of the |
* initial buffer segment before the first word boundary. |
* If the buffer is very short, use unaligned_memcpy(), too. |
*/ |
mod = (uintptr_t) dst & (word_size - 1); |
fill = word_size - mod; |
if (fill > n) fill = n; |
/* Copy the initial segment. */ |
srcb = src; |
dstb = dst; |
i = fill; |
while (i-- != 0) |
*dstb++ = *srcb++; |
/* Compute remaining length. */ |
n -= fill; |
if (n == 0) return dst; |
/* Pointers to aligned segment. */ |
dstw = (unsigned long *) dstb; |
srcw = (const unsigned long *) srcb; |
n_words = n / word_size; /* Number of whole words to copy. */ |
n -= n_words * word_size; /* Remaining bytes at the end. */ |
/* "Fast" copy. */ |
i = n_words; |
while (i-- != 0) |
*dstw++ = *srcw++; |
/* |
* Copy the rest. |
*/ |
srcb = (const uint8_t *) srcw; |
dstb = (uint8_t *) dstw; |
i = n; |
while (i-- != 0) |
*dstb++ = *srcb++; |
return dst; |
} |
/** Move memory block with possible overlapping. */ |
void *memmove(void *dst, const void *src, size_t n) |
{ |
const uint8_t *sp; |
uint8_t *dp; |
/* Nothing to do? */ |
if (src == dst) |
return dst; |
/* Non-overlapping? */ |
if (dst >= src + n || src >= dst + n) { |
return memcpy(dst, src, n); |
} |
/* Which direction? */ |
if (src > dst) { |
/* Forwards. */ |
sp = src; |
dp = dst; |
while (n-- != 0) |
*dp++ = *sp++; |
} else { |
/* Backwards. */ |
sp = src + (n - 1); |
dp = dst + (n - 1); |
while (n-- != 0) |
*dp-- = *sp--; |
} |
return dst; |
} |
/** Compare two memory areas. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/lib/libc/generic/loader.c |
---|
30,10 → 30,11 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <ipc/services.h> |
#include <libc.h> |
#include <task.h> |
#include <string.h> |
46,33 → 47,29 |
/** Connect to a new program loader. |
* |
* Spawns a new program loader task and returns the connection structure. |
* @return Pointer to the loader connection structure (should be |
* de-allocated using free() after use). |
* |
* @param name Symbolic name to set on the newly created task. |
* |
* @return Pointer to the loader connection structure (should be |
* deallocated using free() after use). |
* |
*/ |
loader_t *loader_spawn(void) |
int loader_spawn(const char *name) |
{ |
int phone_id, rc; |
loader_t *ldr; |
return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER, |
(sysarg_t) name, str_size(name)); |
} |
/* |
* Ask kernel to spawn a new loader task. |
*/ |
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id); |
if (rc != 0) |
loader_t *loader_connect(void) |
{ |
int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0); |
if (phone_id < 0) |
return NULL; |
/* |
* Say hello so that the loader knows the incoming connection's |
* phone hash. |
*/ |
rc = async_req_0_0(phone_id, LOADER_HELLO); |
if (rc != EOK) |
return NULL; |
ldr = malloc(sizeof(loader_t)); |
loader_t *ldr = malloc(sizeof(loader_t)); |
if (ldr == NULL) |
return NULL; |
ldr->phone_id = phone_id; |
return ldr; |
} |
81,27 → 78,26 |
* |
* Retrieves the ID of the new task from the loader. |
* |
* @param ldr Loader connection structure. |
* @param task_id Points to a variable where the ID should be stored. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* @param task_id Points to a variable where the ID should be stored. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_get_task_id(loader_t *ldr, task_id_t *task_id) |
{ |
/* Get task ID. */ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
/* Get task ID. */ |
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer); |
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t)); |
aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer); |
int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
ipcarg_t retval; |
async_wait_for(req, &retval); |
return (int)retval; |
return (int) retval; |
} |
/** Set pathname of the program to load. |
110,39 → 106,35 |
* to the current working directory (it will be absolutized before |
* sending to the loader). |
* |
* @param ldr Loader connection structure. |
* @param path Pathname of the program file. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* @param path Pathname of the program file. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_set_pathname(loader_t *ldr, const char *path) |
{ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
char *pa; |
size_t pa_len; |
pa = absolutize(path, &pa_len); |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return 0; |
/* Send program pathname */ |
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len); |
ipc_call_t answer; |
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer); |
int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
free(pa); |
ipcarg_t retval; |
async_wait_for(req, &retval); |
return (int)retval; |
return (int) retval; |
} |
/** Set command-line arguments for the program. |
* |
* Sets the vector of command-line arguments to be passed to the loaded |
149,60 → 141,110 |
* program. By convention, the very first argument is typically the same as |
* the command used to execute the program. |
* |
* @param ldr Loader connection structure. |
* @param argv NULL-terminated array of pointers to arguments. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* @param argv NULL-terminated array of pointers to arguments. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_set_args(loader_t *ldr, char *const argv[]) |
{ |
aid_t req; |
ipc_call_t answer; |
ipcarg_t rc; |
char *const *ap; |
char *dp; |
char *arg_buf; |
size_t buffer_size; |
/* |
/* |
* Serialize the arguments into a single array. First |
* compute size of the buffer needed. |
*/ |
ap = argv; |
buffer_size = 0; |
char *const *ap = argv; |
size_t buffer_size = 0; |
while (*ap != NULL) { |
buffer_size += strlen(*ap) + 1; |
++ap; |
buffer_size += str_size(*ap) + 1; |
ap++; |
} |
arg_buf = malloc(buffer_size); |
if (arg_buf == NULL) return ENOMEM; |
char *arg_buf = malloc(buffer_size); |
if (arg_buf == NULL) |
return ENOMEM; |
/* Now fill the buffer with null-terminated argument strings */ |
ap = argv; |
dp = arg_buf; |
char *dp = arg_buf; |
while (*ap != NULL) { |
strcpy(dp, *ap); |
dp += strlen(*ap) + 1; |
++ap; |
str_cpy(dp, buffer_size - (dp - arg_buf), *ap); |
dp += str_size(*ap) + 1; |
ap++; |
} |
/* Send serialized arguments to the loader */ |
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size); |
ipc_call_t answer; |
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer); |
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &rc); |
if (rc != EOK) return rc; |
if (rc != EOK) |
return rc; |
/* Free temporary buffer */ |
free(arg_buf); |
return EOK; |
} |
/** Set preset files for the program. |
* |
* Sets the vector of preset files to be passed to the loaded |
* program. By convention, the first three files represent stdin, |
* stdout and stderr respectively. |
* |
* @param ldr Loader connection structure. |
* @param files NULL-terminated array of pointers to files. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_set_files(loader_t *ldr, fdi_node_t *const files[]) |
{ |
/* |
* Serialize the arguments into a single array. First |
* compute size of the buffer needed. |
*/ |
fdi_node_t *const *ap = files; |
size_t count = 0; |
while (*ap != NULL) { |
count++; |
ap++; |
} |
fdi_node_t *files_buf; |
files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t)); |
if (files_buf == NULL) |
return ENOMEM; |
/* Fill the buffer */ |
size_t i; |
for (i = 0; i < count; i++) |
files_buf[i] = *files[i]; |
/* Send serialized files to the loader */ |
ipc_call_t answer; |
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer); |
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf, |
count * sizeof(fdi_node_t)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &rc); |
if (rc != EOK) |
return rc; |
/* Free temporary buffer */ |
free(files_buf); |
return EOK; |
} |
211,18 → 253,14 |
* If this function succeeds, the program has been successfully loaded |
* and is ready to be executed. |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_load_program(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD); |
if (rc != EOK) |
return rc; |
return EOK; |
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD); |
} |
/** Instruct loader to execute the program. |
234,17 → 272,19 |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
int loader_run(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_RUN); |
int rc = async_req_0_0(ldr->phone_id, LOADER_RUN); |
if (rc != EOK) |
return rc; |
ipc_hangup(ldr->phone_id); |
ldr->phone_id = 0; |
return EOK; |
} |
254,8 → 294,10 |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
* @param ldr Loader connection structure. |
* |
* @return Zero on success or negative error code. |
* |
*/ |
void loader_abort(loader_t *ldr) |
{ |
/branches/arm/uspace/lib/libc/generic/string.c |
---|
1,7 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com> |
* Copyright (c) 1988, 1993 The Regents of the University of California. |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
35,180 → 34,665 |
*/ |
#include <string.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <assert.h> |
#include <limits.h> |
#include <ctype.h> |
#include <limits.h> |
#include <malloc.h> |
#include <errno.h> |
#include <align.h> |
#include <sys/types.h> |
#include <malloc.h> |
#include <mem.h> |
#include <string.h> |
/* Dummy implementation of mem/ functions */ |
/** Byte mask consisting of lowest @n bits (out of 8) */ |
#define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1)) |
void *memset(void *s, int c, size_t n) |
/** Byte mask consisting of lowest @n bits (out of 32) */ |
#define LO_MASK_32(n) ((uint32_t) ((1 << (n)) - 1)) |
/** Byte mask consisting of highest @n bits (out of 8) */ |
#define HI_MASK_8(n) (~LO_MASK_8(8 - (n))) |
/** Number of data bits in a UTF-8 continuation byte */ |
#define CONT_BITS 6 |
/** Decode a single character from a string. |
* |
* Decode a single character from a string of size @a size. Decoding starts |
* at @a offset and this offset is moved to the beginning of the next |
* character. In case of decoding error, offset generally advances at least |
* by one. However, offset is never moved beyond size. |
* |
* @param str String (not necessarily NULL-terminated). |
* @param offset Byte offset in string where to start decoding. |
* @param size Size of the string (in bytes). |
* |
* @return Value of decoded character, U_SPECIAL on decoding error or |
* NULL if attempt to decode beyond @a size. |
* |
*/ |
wchar_t str_decode(const char *str, size_t *offset, size_t size) |
{ |
char *os = s; |
if (*offset + 1 > size) |
return 0; |
while (n--) |
*(os++) = c; |
/* First byte read from string */ |
uint8_t b0 = (uint8_t) str[(*offset)++]; |
return s; |
/* Determine code length */ |
unsigned int b0_bits; /* Data bits in first byte */ |
unsigned int cbytes; /* Number of continuation bytes */ |
if ((b0 & 0x80) == 0) { |
/* 0xxxxxxx (Plain ASCII) */ |
b0_bits = 7; |
cbytes = 0; |
} else if ((b0 & 0xe0) == 0xc0) { |
/* 110xxxxx 10xxxxxx */ |
b0_bits = 5; |
cbytes = 1; |
} else if ((b0 & 0xf0) == 0xe0) { |
/* 1110xxxx 10xxxxxx 10xxxxxx */ |
b0_bits = 4; |
cbytes = 2; |
} else if ((b0 & 0xf8) == 0xf0) { |
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ |
b0_bits = 3; |
cbytes = 3; |
} else { |
/* 10xxxxxx -- unexpected continuation byte */ |
return U_SPECIAL; |
} |
if (*offset + cbytes > size) |
return U_SPECIAL; |
wchar_t ch = b0 & LO_MASK_8(b0_bits); |
/* Decode continuation bytes */ |
while (cbytes > 0) { |
uint8_t b = (uint8_t) str[(*offset)++]; |
/* Must be 10xxxxxx */ |
if ((b & 0xc0) != 0x80) |
return U_SPECIAL; |
/* Shift data bits to ch */ |
ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS)); |
cbytes--; |
} |
return ch; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
/** Encode a single character to string representation. |
* |
* Encode a single character to string representation (i.e. UTF-8) and store |
* it into a buffer at @a offset. Encoding starts at @a offset and this offset |
* is moved to the position where the next character can be written to. |
* |
* @param ch Input character. |
* @param str Output buffer. |
* @param offset Byte offset where to start writing. |
* @param size Size of the output buffer (in bytes). |
* |
* @return EOK if the character was encoded successfully, EOVERFLOW if there |
* was not enough space in the output buffer or EINVAL if the character |
* code was invalid. |
*/ |
int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size) |
{ |
if (*offset >= size) |
return EOVERFLOW; |
if (!chr_check(ch)) |
return EINVAL; |
/* Unsigned version of ch (bit operations should only be done |
on unsigned types). */ |
uint32_t cc = (uint32_t) ch; |
/* Determine how many continuation bytes are needed */ |
unsigned int b0_bits; /* Data bits in first byte */ |
unsigned int cbytes; /* Number of continuation bytes */ |
if ((cc & ~LO_MASK_32(7)) == 0) { |
b0_bits = 7; |
cbytes = 0; |
} else if ((cc & ~LO_MASK_32(11)) == 0) { |
b0_bits = 5; |
cbytes = 1; |
} else if ((cc & ~LO_MASK_32(16)) == 0) { |
b0_bits = 4; |
cbytes = 2; |
} else if ((cc & ~LO_MASK_32(21)) == 0) { |
b0_bits = 3; |
cbytes = 3; |
} else { |
/* Codes longer than 21 bits are not supported */ |
return EINVAL; |
} |
/* Check for available space in buffer */ |
if (*offset + cbytes >= size) |
return EOVERFLOW; |
/* Encode continuation bytes */ |
unsigned int i; |
for (i = cbytes; i > 0; i--) { |
str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS)); |
cc = cc >> CONT_BITS; |
} |
/* Encode first byte */ |
str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1); |
/* Advance offset */ |
*offset += cbytes + 1; |
return EOK; |
} |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
/** Get size of string. |
* |
* Get the number of bytes which are used by the string @a str (excluding the |
* NULL-terminator). |
* |
* @param str String to consider. |
* |
* @return Number of bytes used by the string |
* |
*/ |
size_t str_size(const char *str) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
size_t size = 0; |
while (*str++ != 0) |
size++; |
return size; |
} |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
/** Get size of wide string. |
* |
* Get the number of bytes which are used by the wide string @a str (excluding the |
* NULL-terminator). |
* |
* @param str Wide string to consider. |
* |
* @return Number of bytes used by the wide string |
* |
*/ |
size_t wstr_size(const wchar_t *str) |
{ |
return (wstr_length(str) * sizeof(wchar_t)); |
} |
/** Get size of string with length limit. |
* |
* Get the number of bytes which are used by up to @a max_len first |
* characters in the string @a str. If @a max_len is greater than |
* the length of @a str, the entire string is measured (excluding the |
* NULL-terminator). |
* |
* @param str String to consider. |
* @param max_len Maximum number of characters to measure. |
* |
* @return Number of bytes used by the characters. |
* |
*/ |
size_t str_lsize(const char *str, size_t max_len) |
{ |
size_t len = 0; |
size_t offset = 0; |
while (len < max_len) { |
if (str_decode(str, &offset, STR_NO_LIMIT) == 0) |
break; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
len++; |
} |
return offset; |
} |
void *memcpy(void *dst, const void *src, size_t n) |
/** Get size of wide string with length limit. |
* |
* Get the number of bytes which are used by up to @a max_len first |
* wide characters in the wide string @a str. If @a max_len is greater than |
* the length of @a str, the entire wide string is measured (excluding the |
* NULL-terminator). |
* |
* @param str Wide string to consider. |
* @param max_len Maximum number of wide characters to measure. |
* |
* @return Number of bytes used by the wide characters. |
* |
*/ |
size_t wstr_lsize(const wchar_t *str, size_t max_len) |
{ |
int i, j; |
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t)); |
} |
if (((long) dst & (sizeof(long) - 1)) || |
((long) src & (sizeof(long) - 1))) |
return unaligned_memcpy(dst, src, n); |
/** Get number of characters in a string. |
* |
* @param str NULL-terminated string. |
* |
* @return Number of characters in string. |
* |
*/ |
size_t str_length(const char *str) |
{ |
size_t len = 0; |
size_t offset = 0; |
while (str_decode(str, &offset, STR_NO_LIMIT) != 0) |
len++; |
return len; |
} |
for (i = 0; i < n / sizeof(unsigned long); i++) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
/** Get number of characters in a wide string. |
* |
* @param str NULL-terminated wide string. |
* |
* @return Number of characters in @a str. |
* |
*/ |
size_t wstr_length(const wchar_t *wstr) |
{ |
size_t len = 0; |
while (*wstr++ != 0) |
len++; |
return len; |
} |
void *memmove(void *dst, const void *src, size_t n) |
/** Get number of characters in a string with size limit. |
* |
* @param str NULL-terminated string. |
* @param size Maximum number of bytes to consider. |
* |
* @return Number of characters in string. |
* |
*/ |
size_t str_nlength(const char *str, size_t size) |
{ |
int i, j; |
size_t len = 0; |
size_t offset = 0; |
if (src > dst) |
return memcpy(dst, src, n); |
while (str_decode(str, &offset, size) != 0) |
len++; |
return len; |
} |
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--) |
((unsigned char *) ((unsigned long *) dst))[j] = |
((unsigned char *) ((unsigned long *) src))[j]; |
/** Get number of characters in a string with size limit. |
* |
* @param str NULL-terminated string. |
* @param size Maximum number of bytes to consider. |
* |
* @return Number of characters in string. |
* |
*/ |
size_t wstr_nlength(const wchar_t *str, size_t size) |
{ |
size_t len = 0; |
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t)); |
size_t offset = 0; |
while ((offset < limit) && (*str++ != 0)) { |
len++; |
offset += sizeof(wchar_t); |
} |
return len; |
} |
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
return (char *) dst; |
/** Check whether character is plain ASCII. |
* |
* @return True if character is plain ASCII. |
* |
*/ |
bool ascii_check(wchar_t ch) |
{ |
if ((ch >= 0) && (ch <= 127)) |
return true; |
return false; |
} |
/** Compare two memory areas. |
/** Check whether character is valid |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
* @return True if character is a valid Unicode code point. |
* |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
bool chr_check(wchar_t ch) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
if ((ch >= 0) && (ch <= 1114111)) |
return true; |
return false; |
} |
/** Count the number of characters in the string, not including terminating 0. |
/** Compare two NULL terminated strings. |
* |
* @param str String. |
* @return Number of characters in string. |
* Do a char-by-char comparison of two NULL-terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths. |
* |
* @param s1 First string to compare. |
* @param s2 Second string to compare. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
size_t strlen(const char *str) |
int str_cmp(const char *s1, const char *s2) |
{ |
size_t counter = 0; |
wchar_t c1 = 0; |
wchar_t c2 = 0; |
size_t off1 = 0; |
size_t off2 = 0; |
while (str[counter] != 0) |
counter++; |
while (true) { |
c1 = str_decode(s1, &off1, STR_NO_LIMIT); |
c2 = str_decode(s2, &off2, STR_NO_LIMIT); |
return counter; |
if (c1 < c2) |
return -1; |
if (c1 > c2) |
return 1; |
if (c1 == 0 || c2 == 0) |
break; |
} |
return 0; |
} |
int strcmp(const char *a, const char *b) |
/** Compare two NULL terminated strings with length limit. |
* |
* Do a char-by-char comparison of two NULL-terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths and the length limit. |
* |
* @param s1 First string to compare. |
* @param s2 Second string to compare. |
* @param max_len Maximum number of characters to consider. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
int str_lcmp(const char *s1, const char *s2, size_t max_len) |
{ |
int c = 0; |
wchar_t c1 = 0; |
wchar_t c2 = 0; |
while (a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
size_t off1 = 0; |
size_t off2 = 0; |
return (a[c] - b[c]); |
size_t len = 0; |
while (true) { |
if (len >= max_len) |
break; |
c1 = str_decode(s1, &off1, STR_NO_LIMIT); |
c2 = str_decode(s2, &off2, STR_NO_LIMIT); |
if (c1 < c2) |
return -1; |
if (c1 > c2) |
return 1; |
if (c1 == 0 || c2 == 0) |
break; |
++len; |
} |
return 0; |
} |
int strncmp(const char *a, const char *b, size_t n) |
/** Copy string. |
* |
* Copy source string @a src to destination buffer @a dest. |
* No more than @a size bytes are written. If the size of the output buffer |
* is at least one byte, the output string will always be well-formed, i.e. |
* null-terminated and containing only complete characters. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
*/ |
void str_cpy(char *dest, size_t size, const char *src) |
{ |
size_t c = 0; |
wchar_t ch; |
size_t src_off; |
size_t dest_off; |
while (c < n && a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
/* There must be space for a null terminator in the buffer. */ |
assert(size > 0); |
return ( c < n ? a[c] - b[c] : 0); |
src_off = 0; |
dest_off = 0; |
while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
dest[dest_off] = '\0'; |
} |
/** Copy size-limited substring. |
* |
* Copy prefix of string @a src of max. size @a size to destination buffer |
* @a dest. No more than @a size bytes are written. The output string will |
* always be well-formed, i.e. null-terminated and containing only complete |
* characters. |
* |
* No more than @a n bytes are read from the input string, so it does not |
* have to be null-terminated. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
* @param n Maximum number of bytes to read from @a src. |
*/ |
void str_ncpy(char *dest, size_t size, const char *src, size_t n) |
{ |
wchar_t ch; |
size_t src_off; |
size_t dest_off; |
/* There must be space for a null terminator in the buffer. */ |
assert(size > 0); |
src_off = 0; |
dest_off = 0; |
while ((ch = str_decode(src, &src_off, n)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
dest[dest_off] = '\0'; |
} |
int stricmp(const char *a, const char *b) |
/** Append one string to another. |
* |
* Append source string @a src to string in destination buffer @a dest. |
* Size of the destination buffer is @a dest. If the size of the output buffer |
* is at least one byte, the output string will always be well-formed, i.e. |
* null-terminated and containing only complete characters. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer. |
* @param src Source string. |
*/ |
void str_append(char *dest, size_t size, const char *src) |
{ |
int c = 0; |
size_t dstr_size; |
dstr_size = str_size(dest); |
str_cpy(dest + dstr_size, size - dstr_size, src); |
} |
/** Copy NULL-terminated wide string to string |
* |
* Copy source wide string @a src to destination buffer @a dst. |
* No more than @a size bytes are written. NULL-terminator is always |
* written after the last succesfully copied character (i.e. if the |
* destination buffer is has at least 1 byte, it will be always |
* NULL-terminated). |
* |
* @param src Source wide string. |
* @param dst Destination buffer. |
* @param count Size of the destination buffer. |
* |
*/ |
void wstr_nstr(char *dst, const wchar_t *src, size_t size) |
{ |
/* No space for the NULL-terminator in the buffer */ |
if (size == 0) |
return; |
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
c++; |
wchar_t ch; |
size_t src_idx = 0; |
size_t dst_off = 0; |
return (tolower(a[c]) - tolower(b[c])); |
while ((ch = src[src_idx++]) != 0) { |
if (chr_encode(ch, dst, &dst_off, size) != EOK) |
break; |
} |
if (dst_off >= size) |
dst[size - 1] = 0; |
else |
dst[dst_off] = 0; |
} |
/** Return pointer to the first occurence of character c in string. |
/** Find first occurence of character in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
* @param str String to search. |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
char *strchr(const char *str, int c) |
const char *str_chr(const char *str, wchar_t ch) |
{ |
while (*str != '\0') { |
if (*str == (char) c) |
return (char *) str; |
str++; |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + last); |
last = off; |
} |
return NULL; |
} |
/** Return pointer to the last occurence of character c in string. |
/** Find last occurence of character in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
* @param str String to search. |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
char *strrchr(const char *str, int c) |
const char *str_rchr(const char *str, wchar_t ch) |
{ |
char *retval = NULL; |
while (*str != '\0') { |
if (*str == (char) c) |
retval = (char *) str; |
str++; |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
const char *res = NULL; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
res = (str + last); |
last = off; |
} |
return res; |
} |
return (char *) retval; |
/** Insert a wide character into a wide string. |
* |
* Insert a wide character into a wide string at position |
* @a pos. The characters after the position are shifted. |
* |
* @param str String to insert to. |
* @param ch Character to insert to. |
* @param pos Character index where to insert. |
@ @param max_pos Characters in the buffer. |
* |
* @return True if the insertion was sucessful, false if the position |
* is out of bounds. |
* |
*/ |
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos) |
{ |
size_t len = wstr_length(str); |
if ((pos > len) || (pos + 1 > max_pos)) |
return false; |
size_t i; |
for (i = len; i + 1 > pos; i--) |
str[i + 1] = str[i]; |
str[pos] = ch; |
return true; |
} |
/** Remove a wide character from a wide string. |
* |
* Remove a wide character from a wide string at position |
* @a pos. The characters after the position are shifted. |
* |
* @param str String to remove from. |
* @param pos Character index to remove. |
* |
* @return True if the removal was sucessful, false if the position |
* is out of bounds. |
* |
*/ |
bool wstr_remove(wchar_t *str, size_t pos) |
{ |
size_t len = wstr_length(str); |
if (pos >= len) |
return false; |
size_t i; |
for (i = pos + 1; i <= len; i++) |
str[i - 1] = str[i]; |
return true; |
} |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
c++; |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* |
358,91 → 842,47 |
return (sgn ? -number : number); |
} |
char *strcpy(char *dest, const char *src) |
char *str_dup(const char *src) |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++))) |
; |
return orig; |
} |
size_t size = str_size(src); |
void *dest = malloc(size + 1); |
char *strncpy(char *dest, const char *src, size_t n) |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++)) && --n) |
; |
return orig; |
} |
if (dest == NULL) |
return (char *) NULL; |
char *strcat(char *dest, const char *src) |
{ |
char *orig = dest; |
while (*dest++) |
; |
--dest; |
while ((*dest++ = *src++)) |
; |
return orig; |
return (char *) memcpy(dest, src, size + 1); |
} |
char * strdup(const char *s1) |
char *strtok(char *s, const char *delim) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
static char *next; |
if (ret == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
return strtok_r(s, delim, &next); |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * strtok_r(char *s, const char *delim, char **last) |
char *strtok_r(char *s, const char *delim, char **next) |
{ |
char *spanp, *tok; |
int c, sc; |
char *start, *end; |
if (s == NULL && (s = *last) == NULL) |
return (NULL); |
if (s == NULL) |
s = *next; |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) |
goto cont; |
} |
/* Skip over leading delimiters. */ |
while (*s && (str_chr(delim, *s) != NULL)) ++s; |
start = s; |
if (c == 0) { /* no non-delimiter characters */ |
*last = NULL; |
return (NULL); |
} |
/* Skip over token characters. */ |
while (*s && (str_chr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
tok = s - 1; |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = '\0'; |
*last = s; |
return (tok); |
} |
} while (sc != 0); |
if (start == end) { |
return NULL; /* No more tokens. */ |
} |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * strtok(char *s, const char *delim) |
{ |
static char *last; |
return (strtok_r(s, delim, &last)); |
/* Overwrite delimiter with NULL terminator. */ |
*end = '\0'; |
return start; |
} |
/** @} |
/branches/arm/uspace/lib/libc/generic/ddi.c |
---|
33,26 → 33,42 |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <libc.h> |
#include <task.h> |
#include <as.h> |
#include <align.h> |
#include <libarch/config.h> |
#include <kernel/ddi/ddi_arg.h> |
/** Return unique device number. |
* |
* @return New unique device number. |
* |
*/ |
int device_assign_devno(void) |
{ |
return __SYSCALL0(SYS_DEVICE_ASSIGN_DEVNO); |
} |
/** Map piece of physical memory to task. |
* |
* Caller of this function must have the CAP_MEM_MANAGER capability. |
* |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the sterting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the starting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in creating address space area. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_MEM_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in creating address space area. |
*/ |
int physmem_map(void *pf, void *vp, unsigned long pages, int flags) |
{ |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags); |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, |
flags); |
} |
/** Enable I/O space range to task. |
59,13 → 75,14 |
* |
* Caller of this function must have the IO_MEM_MANAGER capability. |
* |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in allocating memory. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_IO_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in allocating memory. |
*/ |
int iospace_enable(task_id_t id, void *ioaddr, unsigned long size) |
{ |
80,7 → 97,7 |
/** Interrupt control |
* |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
*/ |
int preemption_control(int enable) |
{ |
87,5 → 104,36 |
return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable); |
} |
/** Enable PIO for specified I/O range. |
* |
* @param pio_addr I/O start address. |
* @param size Size of the I/O region. |
* @param use_addr Address where the final address for application's PIO |
* will be stored. |
* |
* @return Zero on success or negative error code. |
*/ |
int pio_enable(void *pio_addr, size_t size, void **use_addr) |
{ |
void *phys; |
void *virt; |
size_t offset; |
unsigned int pages; |
#ifdef IO_SPACE_BOUNDARY |
if (pio_addr < IO_SPACE_BOUNDARY) { |
*use_addr = pio_addr; |
return iospace_enable(task_get_id(), pio_addr, size); |
} |
#endif |
phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); |
offset = pio_addr - phys; |
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH; |
virt = as_get_mappable_page(pages << PAGE_WIDTH); |
*use_addr = virt + offset; |
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/thread.c |
---|
108,8 → 108,8 |
uarg->uspace_thread_arg = arg; |
uarg->uspace_uarg = uarg; |
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) tid); |
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) str_size(name), (sysarg_t) tid); |
if (rc) { |
/* |
130,6 → 130,8 |
void thread_exit(int status) |
{ |
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status); |
for (;;) |
; |
} |
/** Detach thread. |
152,6 → 154,7 |
*/ |
int thread_join(thread_id_t thread) |
{ |
return 0; |
} |
/** Get current thread ID. |
/branches/arm/uspace/lib/libc/generic/sysinfo.c |
---|
38,7 → 38,8 |
sysarg_t sysinfo_value(char *name) |
{ |
return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t ) name, (sysarg_t) strlen(name)); |
return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t ) name, |
(sysarg_t) str_size(name)); |
} |
/** @} |
/branches/arm/uspace/lib/libc/generic/event.c |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
* @} |
*/ |
/** @addtogroup libc |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <event.h> |
#include <kernel/ipc/event_types.h> |
#include <ipc/ipc.h> |
/** Subscribe for event notifications. |
* |
* @param evno Event number. |
* @param method Use this method for notifying me. |
* |
* @return Value returned by the kernel. |
*/ |
int event_subscribe(event_type_t e, ipcarg_t method) |
{ |
return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method); |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/generic/time.c |
---|
47,6 → 47,8 |
#include <as.h> |
#include <ddi.h> |
#include <time.h> |
/* Pointers to public variables with time */ |
struct { |
volatile sysarg_t seconds1; |
/branches/arm/uspace/lib/libc/generic/tls.c |
---|
116,7 → 116,7 |
tcb_t *tcb; |
size = ALIGN_UP(size, &_tls_alignment); |
*data = memalign(&_tls_alignment, sizeof(tcb_t) + size); |
*data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size); |
tcb = (tcb_t *) (*data + size); |
tcb->self = tcb; |
/branches/arm/uspace/lib/libc/generic/smc.c |
---|
34,6 → 34,7 |
#include <libc.h> |
#include <sys/types.h> |
#include <smc.h> |
int smc_coherence(void *address, size_t size) |
{ |
/branches/arm/uspace/lib/libc/generic/udebug.c |
---|
34,7 → 34,6 |
#include <udebug.h> |
#include <sys/types.h> |
#include <syscall.h> |
#include <ipc/ipc.h> |
#include <async.h> |
/branches/arm/uspace/lib/libc/arch/ppc64/include/thread.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/fibril.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/syscall.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/atomic.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/regname.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/stackarg.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/faddr.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/limits.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/tls.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/types.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/include/config.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/Makefile.inc |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/src/syscall.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/src/entry.s |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/src/tls.c |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/src/fibril.S |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/src/thread_entry.s |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc64/_link.ld.in |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/sparc64/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/sparc64/include/stack.h |
---|
45,6 → 45,11 |
*/ |
#define STACK_WINDOW_SAVE_AREA_SIZE (16 * STACK_ITEM_SIZE) |
/* |
* Six extended words for first six arguments. |
*/ |
#define STACK_ARG_SAVE_AREA_SIZE (6 * STACK_ITEM_SIZE) |
/** |
* By convention, the actual top of the stack is %sp + STACK_BIAS. |
*/ |
/branches/arm/uspace/lib/libc/arch/sparc64/include/fibril.h |
---|
39,7 → 39,7 |
#include <sys/types.h> |
#include <align.h> |
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE |
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE) |
#ifdef context_set |
#undef context_set |
/branches/arm/uspace/lib/libc/arch/sparc64/include/types.h |
---|
47,6 → 47,9 |
typedef unsigned int uint32_t; |
typedef unsigned long int uint64_t; |
typedef int64_t ssize_t; |
typedef uint64_t size_t; |
typedef uint64_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/sparc64/include/ddi.h |
---|
0,0 → 1,92 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libsparc64 |
*/ |
#ifndef LIBC_sparc64_DDI_H_ |
#define LIBC_sparc64_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline memory_barrier(void) |
{ |
asm volatile ("membar #LoadLoad | #StoreStore\n" ::: "memory"); |
} |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uint8_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uint16_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uint32_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
#endif |
/branches/arm/uspace/lib/libc/arch/sparc64/include/syscall.h |
---|
38,6 → 38,14 |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall |
#define __syscall1 __syscall |
#define __syscall2 __syscall |
#define __syscall3 __syscall |
#define __syscall4 __syscall |
#define __syscall5 __syscall |
#define __syscall6 __syscall |
static inline sysarg_t |
__syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3, |
const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, const syscall_t id) |
/branches/arm/uspace/lib/libc/arch/sparc64/Makefile.inc |
---|
29,18 → 29,16 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mcpu=ultrasparc -m64 |
LFLAGS += -no-check-sections -N |
ENDIANESS = BE |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
/branches/arm/uspace/lib/libc/arch/sparc64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
31,13 → 31,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(.sbss); |
*(COMMON); |
/branches/arm/uspace/lib/libc/arch/ia64/Makefile.inc |
---|
29,19 → 29,18 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16 |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/ddi.c |
CFLAGS += -fno-unwind-tables |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ENDIANESS = LE |
BFD_NAME = elf64-ia64-little |
BFD_ARCH = ia64-elf64 |
/branches/arm/uspace/lib/libc/arch/ia64/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ia64/include/types.h |
---|
47,6 → 47,9 |
typedef unsigned int uint32_t; |
typedef unsigned long int uint64_t; |
typedef int64_t ssize_t; |
typedef uint64_t size_t; |
typedef uint64_t uintptr_t; |
typedef unsigned char __r8; /* Reserve byte */ |
/branches/arm/uspace/lib/libc/arch/ia64/include/ddi.h |
---|
0,0 → 1,115 |
/* |
* Copyright (c) 2005 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 libcia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ia64_DDI_H_ |
#define LIBC_ia64_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
#define IO_SPACE_BOUNDARY (64 * 1024) |
uint64_t get_ia64_iospace_address(void); |
extern uint64_t ia64_iospace_address; |
#define IA64_IOSPACE_ADDRESS \ |
(ia64_iospace_address ? \ |
ia64_iospace_address : \ |
(ia64_iospace_address = get_ia64_iospace_address())) |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libc/arch/ia64/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_ia64_SYSCALL_H_ |
#define LIBC_ia64_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/arm/uspace/lib/libc/arch/ia64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
32,13 → 32,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(.sbss); |
*(.scommon); |
/branches/arm/uspace/lib/libc/arch/ia64/src/entry.s |
---|
38,7 → 38,7 |
# |
__entry: |
alloc loc0 = ar.pfs, 0, 1, 2, 0 |
mov r1 = _gp |
movl r1 = _gp |
# Pass PCB pointer as the first argument to __main |
mov out0 = r2 |
/branches/arm/uspace/lib/libc/arch/ia64/src/thread_entry.s |
---|
36,7 → 36,7 |
__thread_entry: |
alloc loc0 = ar.pfs, 0, 1, 1, 0 |
mov r1 = _gp |
movl r1 = _gp |
# |
# r8 contains address of uarg structure. |
/branches/arm/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/arm/uspace/lib/libc/arch/arm32/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/arm32/include/tls.h |
---|
40,7 → 40,7 |
#define CONFIG_TLS_VARIANT_1 |
/** Offsets for accessing __thread variables are shifted 8 bytes higher. */ |
/** Offsets for accessing thread-local variables are shifted 8 bytes higher. */ |
#define ARM_TP_OFFSET (-8) |
/** TCB (Thread Control Block) struct. |
/branches/arm/uspace/lib/libc/arch/arm32/include/types.h |
---|
48,6 → 48,9 |
typedef unsigned long int uint32_t; |
typedef unsigned long long int uint64_t; |
typedef int32_t ssize_t; |
typedef uint32_t size_t; |
typedef uint32_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/arm32/include/fibril.h |
---|
38,7 → 38,7 |
#include <sys/types.h> |
#include <align.h> |
#include "thread.h" |
#include <thread.h> |
/** Size of a stack item */ |
#define STACK_ITEM_SIZE 4 |
/branches/arm/uspace/lib/libc/arch/arm32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcarm32 |
*/ |
#ifndef LIBC_arm32_DDI_H_ |
#define LIBC_arm32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/arm/uspace/lib/libc/arch/arm32/include/syscall.h |
---|
30,12 → 30,14 |
* @{ |
*/ |
/** @file |
* @brief Empty. |
* @brief |
*/ |
#ifndef LIBC_arm32_SYSCALL_H_ |
#define LIBC_arm32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/arm/uspace/lib/libc/arch/arm32/Makefile.inc |
---|
30,20 → 30,18 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
CFLAGS += -ffixed-r9 -mtp=soft |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/eabi.S |
CFLAGS += -ffixed-r9 -mtp=soft |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c \ |
arch/$(ARCH)/src/eabi.S |
ENDIANESS = LE |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
/branches/arm/uspace/lib/libc/arch/arm32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
28,13 → 28,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(.sbss); |
*(.scommon); |
/branches/arm/uspace/lib/libc/arch/mips32eb/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/mips32eb/include/ddi.h |
---|
0,0 → 1,0 |
link ../../mips32/include/ddi.h |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/arm/uspace/lib/libc/arch/mips32eb/Makefile.inc |
---|
29,19 → 29,17 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = mips-sgi-irix5 |
TARGET = mips-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mips3 |
LFLAGS += -N |
ENDIANESS = BE |
BFD_ARCH = mips |
BFD_NAME = elf32-big |
BFD_NAME = elf32-tradbigmips |
/branches/arm/uspace/lib/libc/arch/ppc32/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ppc32/include/types.h |
---|
47,6 → 47,9 |
typedef unsigned int uint32_t; |
typedef unsigned long long int uint64_t; |
typedef int32_t ssize_t; |
typedef uint32_t size_t; |
typedef uint32_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/ppc32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcppc32 |
*/ |
#ifndef LIBC_ppc32_DDI_H_ |
#define LIBC_ppc32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/arm/uspace/lib/libc/arch/ppc32/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_ppc32_SYSCALL_H_ |
#define LIBC_ppc32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/arm/uspace/lib/libc/arch/ppc32/Makefile.inc |
---|
29,20 → 29,18 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
LFLAGS += -N |
ENDIANESS = BE |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
/branches/arm/uspace/lib/libc/arch/ppc32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
27,13 → 27,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(.sbss); |
*(COMMON); |
/branches/arm/uspace/lib/libc/arch/ppc32/src/entry.s |
---|
34,11 → 34,12 |
## User-space task entry point |
# |
# r3 contains the PCB pointer |
# r6 contains the PCB pointer |
# |
__entry: |
# Pass the PCB pointer to __main() as the first argument. |
# Since the first argument is passed in r3, no operation is needed. |
# The first argument is passed in r3. |
mr %r3, %r6 |
bl __main |
bl __exit |
/branches/arm/uspace/lib/libc/arch/amd64/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/amd64/include/types.h |
---|
47,6 → 47,9 |
typedef unsigned int uint32_t; |
typedef unsigned long long int uint64_t; |
typedef int64_t ssize_t; |
typedef uint64_t size_t; |
typedef uint64_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/amd64/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_amd64_SYSCALL_H_ |
#define LIBC_amd64_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/arm/uspace/lib/libc/arch/amd64/Makefile.inc |
---|
29,18 → 29,16 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
LFLAGS += -N |
ENDIANESS = LE |
BFD_NAME = elf64-x86-64 |
BFD_ARCH = i386:x86-64 |
/branches/arm/uspace/lib/libc/arch/amd64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
26,13 → 26,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(COMMON); |
*(.bss); |
/branches/arm/uspace/lib/libc/arch/mips32/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/mips32/include/types.h |
---|
48,6 → 48,9 |
typedef unsigned long int uint32_t; |
typedef unsigned long long int uint64_t; |
typedef int32_t ssize_t; |
typedef uint32_t size_t; |
typedef uint32_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/mips32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcmips32 |
*/ |
#ifndef LIBC_mips32_DDI_H_ |
#define LIBC_mips32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/arm/uspace/lib/libc/arch/mips32/include/atomic.h |
---|
59,13 → 59,14 |
asm volatile ( |
"1:\n" |
" ll %0, %1\n" |
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" addu %0, %0, %3\n" /* same as add, but never traps on overflow */ |
" move %2, %0\n" |
" sc %0, %1\n" |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
/* nop */ /* nop is inserted automatically by compiler */ |
" nop\n" |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "i" (i), "i" (0) |
: "r" (i), "i" (0) |
); |
return v; |
/branches/arm/uspace/lib/libc/arch/mips32/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_mips32_SYSCALL_H_ |
#define LIBC_mips32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/arm/uspace/lib/libc/arch/mips32/Makefile.inc |
---|
29,23 → 29,16 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
CFLAGS += -mips3 |
-include ../../Makefile.config |
ifeq ($(CONFIG_MIPS_FPU),y) |
CFLAGS += -DCONFIG_MIPS_FPU |
endif |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
CFLAGS += -mips3 |
ENDIANESS = LE |
BFD_ARCH = mips |
BFD_NAME = elf32-tradlittlemips |
/branches/arm/uspace/lib/libc/arch/mips32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
33,13 → 33,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.sbss : { |
*(.scommon); |
/branches/arm/uspace/lib/libc/arch/ia32/include/byteorder.h |
---|
File deleted |
/branches/arm/uspace/lib/libc/arch/ia32/include/types.h |
---|
47,6 → 47,9 |
typedef unsigned int uint32_t; |
typedef unsigned long long int uint64_t; |
typedef int32_t ssize_t; |
typedef uint32_t size_t; |
typedef uint32_t uintptr_t; |
#endif |
/branches/arm/uspace/lib/libc/arch/ia32/include/ddi.h |
---|
33,43 → 33,72 |
#ifndef LIBC_ia32_DDI_H_ |
#define LIBC_ia32_DDI_H_ |
static inline void outb(int16_t port, uint8_t b) |
#include <sys/types.h> |
#include <libarch/types.h> |
#define IO_SPACE_BOUNDARY ((void *) (64 * 1024)) |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port)); |
uint8_t val; |
asm volatile ( |
"inb %w[port], %b[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline void outw(int16_t port, int16_t w) |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port)); |
uint16_t val; |
asm volatile ( |
"inw %w[port], %w[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline void outl(int16_t port, uint32_t l) |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port)); |
uint32_t val; |
asm volatile ( |
"inl %w[port], %[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline uint8_t inb(int16_t port) |
static inline void pio_write_8(ioport8_t *port, uint8_t val) |
{ |
uint8_t val; |
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outb %b[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
static inline int16_t inw(int16_t port) |
static inline void pio_write_16(ioport16_t *port, uint16_t val) |
{ |
int16_t val; |
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outw %w[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
static inline uint32_t inl(int16_t port) |
static inline void pio_write_32(ioport32_t *port, uint32_t val) |
{ |
uint32_t val; |
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outl %[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
#endif |
/branches/arm/uspace/lib/libc/arch/ia32/include/syscall.h |
---|
36,8 → 36,25 |
#ifndef LIBC_ia32_SYSCALL_H_ |
#define LIBC_ia32_SYSCALL_H_ |
#include <syscall.h> |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall_sysenter |
#define __syscall1 __syscall_sysenter |
#define __syscall2 __syscall_sysenter |
#define __syscall3 __syscall_sysenter |
#define __syscall4 __syscall_sysenter |
#define __syscall5 __syscall_int |
#define __syscall6 __syscall_int |
extern sysarg_t |
__syscall_sysenter(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t, |
const sysarg_t, const sysarg_t, const syscall_t); |
extern sysarg_t |
__syscall_int(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t, |
const sysarg_t, const sysarg_t, const syscall_t); |
#endif |
/** @} |
/branches/arm/uspace/lib/libc/arch/ia32/Makefile.inc |
---|
29,19 → 29,17 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c \ |
arch/$(ARCH)/src/setjmp.S |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/setjmp.S |
LFLAGS += -N |
ENDIANESS = LE |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
/branches/arm/uspace/lib/libc/arch/ia32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
26,13 → 26,11 |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
_tls_alignment = ALIGNOF(.tdata); |
.bss : { |
*(COMMON); |
*(.bss); |
/branches/arm/uspace/lib/libc/arch/ia32/src/syscall.S |
---|
28,14 → 28,14 |
.text |
/** Syscall wrapper. |
/** Syscall wrapper - INT $0x30 version. |
* |
* Mind the order of arguments. First two arguments and the syscall number go to |
* scratch registers. An optimized version of this wrapper for fewer arguments |
* could benefit from this and not save unused registers on the stack. |
*/ |
.global __syscall |
__syscall: |
.global __syscall_int |
__syscall_int: |
pushl %ebx |
pushl %esi |
pushl %edi |
53,3 → 53,38 |
popl %esi |
popl %ebx |
ret |
/** Syscall wrapper - SYSENTER version. |
* |
* This is an optimized version of syscall for four or less arguments. Note |
* that EBP and EDI are used to remember user stack address and the return |
* address. The kernel part doesn't save DS, ES and FS so the handler restores |
* these to the selector immediately following CS (it must be the flat data |
* segment, otherwise the SYSENTER wouldn't work in the first place). |
*/ |
.global __syscall_sysenter |
__syscall_sysenter: |
pushl %ebx |
pushl %esi |
pushl %edi |
pushl %ebp |
mov %esp, %ebp |
lea ra, %edi |
movl 20(%esp), %edx # First argument. |
movl 24(%esp), %ecx # Second argument. |
movl 28(%esp), %ebx # Third argument. |
movl 32(%esp), %esi # Fourth argument. |
movl 44(%esp), %eax # Syscall number. |
sysenter |
ra: |
movw %cs, %cx |
addw $8, %cx |
movw %cx, %ds |
movw %cx, %es |
movw %cx, %fs |
popl %ebp |
popl %edi |
popl %esi |
popl %ebx |
ret |
/branches/arm/uspace/lib/libc/Makefile |
---|
31,26 → 31,29 |
LIBC_PREFIX = $(shell pwd) |
SOFTINT_PREFIX = ../softint |
CONSOLE_PREFIX = ../../srv/console |
## Setup toolchain |
# |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I$(CONSOLE_PREFIX) |
## Sources |
# |
GENERIC_SOURCES = \ |
generic/libc.c \ |
generic/ddi.c \ |
generic/as.c \ |
generic/cap.c \ |
generic/devmap.c \ |
generic/event.c \ |
generic/errno.c \ |
generic/mem.c \ |
generic/string.c \ |
generic/fibril.c \ |
generic/fibril_sync.c \ |
generic/pcb.c \ |
generic/smc.c \ |
generic/thread.c \ |
60,21 → 63,20 |
generic/io/asprintf.c \ |
generic/io/io.c \ |
generic/io/printf.c \ |
generic/io/stream.c \ |
generic/io/sprintf.c \ |
generic/io/klog.c \ |
generic/io/snprintf.c \ |
generic/io/vprintf.c \ |
generic/io/vsprintf.c \ |
generic/io/vsnprintf.c \ |
generic/io/printf_core.c \ |
malloc/malloc.c \ |
generic/io/console.c \ |
generic/malloc.c \ |
generic/sysinfo.c \ |
generic/ipc.c \ |
generic/async.c \ |
generic/loader.c \ |
generic/getopt.c \ |
generic/libadt/list.o \ |
generic/libadt/hash_table.o \ |
generic/adt/list.o \ |
generic/adt/hash_table.o \ |
generic/time.c \ |
generic/err.c \ |
generic/stdlib.c \ |
84,34 → 86,35 |
generic/vfs/canonify.c |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/entry.s \ |
arch/$(ARCH)/src/thread_entry.s |
arch/$(UARCH)/src/entry.s \ |
arch/$(UARCH)/src/thread_entry.s |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS) |
.PHONY: all clean depend kerninc |
all: kerninc libc.a arch/$(ARCH)/_link.ld |
all: kerninc libc.a arch/$(UARCH)/_link.ld |
kerninc: |
ln -sfn ../../../../kernel/generic/include include/kernel |
ln -sfn kernel/arch include/arch |
ln -sfn ../arch/$(ARCH)/include include/libarch |
ln -sfn ../arch/$(UARCH)/include include/libarch |
-include Makefile.depend |
clean: |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(ARCH)/_link.ld Makefile.depend |
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \; |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend |
find generic/ arch/$(UARCH)/ -name '*.o' -follow -exec rm \{\} \; |
depend: kerninc |
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
/branches/arm/uspace/lib/libc/Makefile.toolchain |
---|
26,16 → 26,27 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
DEFS = -DARCH=$(ARCH) |
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include |
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \ |
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \ |
-finput-charset=UTF-8 -fno-builtin -Wall -Wextra -Wno-unused-parameter \ |
-Wmissing-prototypes -Werror-implicit-function-declaration -nostdlib \ |
-nostdinc -pipe -g -D__$(ENDIANESS)__ |
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS = |
#-Werror |
## Cross-toolchain prefix |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
## Setup platform configuration |
# |
include $(LIBC_PREFIX)/arch/$(ARCH)/Makefile.inc |
-include $(LIBC_PREFIX)/../../../Makefile.config |
-include $(LIBC_PREFIX)/../../../config.defs |
-include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc |
## Simple detection of the host system |
# |
59,6 → 70,7 |
AR = $(BINUTILS_PREFIX)ar |
OBJCOPY = $(BINUTILS_PREFIX)objcopy |
OBJDUMP = $(BINUTILS_PREFIX)objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),icc_native) |
68,6 → 80,7 |
AR = ar |
OBJCOPY = objcopy |
OBJDUMP = objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),gcc_cross) |
77,5 → 90,5 |
AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar |
OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
/branches/arm/uspace/lib/libblock/libblock.c |
---|
0,0 → 1,604 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libblock |
* @{ |
*/ |
/** |
* @file |
* @brief |
*/ |
#include "libblock.h" |
#include "../../srv/vfs/vfs.h" |
#include <ipc/devmap.h> |
#include <ipc/bd.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <sys/mman.h> |
#include <async.h> |
#include <ipc/ipc.h> |
#include <as.h> |
#include <assert.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <adt/hash_table.h> |
#include <mem.h> |
/** Lock protecting the device connection list */ |
static FIBRIL_MUTEX_INITIALIZE(dcl_lock); |
/** Device connection list head. */ |
static LIST_INITIALIZE(dcl_head); |
#define CACHE_BUCKETS_LOG2 10 |
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) |
typedef struct { |
fibril_mutex_t lock; |
size_t block_size; /**< Block size. */ |
unsigned block_count; /**< Total number of blocks. */ |
unsigned blocks_cached; /**< Number of cached blocks. */ |
hash_table_t block_hash; |
link_t free_head; |
enum cache_mode mode; |
} cache_t; |
typedef struct { |
link_t link; |
dev_handle_t dev_handle; |
int dev_phone; |
fibril_mutex_t com_area_lock; |
void *com_area; |
size_t com_size; |
void *bb_buf; |
off_t bb_off; |
size_t bb_size; |
cache_t *cache; |
} devcon_t; |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static devcon_t *devcon_search(dev_handle_t dev_handle) |
{ |
link_t *cur; |
fibril_mutex_lock(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *devcon = list_get_instance(cur, devcon_t, link); |
if (devcon->dev_handle == dev_handle) { |
fibril_mutex_unlock(&dcl_lock); |
return devcon; |
} |
} |
fibril_mutex_unlock(&dcl_lock); |
return NULL; |
} |
static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area, |
size_t com_size) |
{ |
link_t *cur; |
devcon_t *devcon; |
devcon = malloc(sizeof(devcon_t)); |
if (!devcon) |
return ENOMEM; |
link_initialize(&devcon->link); |
devcon->dev_handle = dev_handle; |
devcon->dev_phone = dev_phone; |
fibril_mutex_initialize(&devcon->com_area_lock); |
devcon->com_area = com_area; |
devcon->com_size = com_size; |
devcon->bb_buf = NULL; |
devcon->bb_off = 0; |
devcon->bb_size = 0; |
devcon->cache = NULL; |
fibril_mutex_lock(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *d = list_get_instance(cur, devcon_t, link); |
if (d->dev_handle == dev_handle) { |
fibril_mutex_unlock(&dcl_lock); |
free(devcon); |
return EEXIST; |
} |
} |
list_append(&devcon->link, &dcl_head); |
fibril_mutex_unlock(&dcl_lock); |
return EOK; |
} |
static void devcon_remove(devcon_t *devcon) |
{ |
fibril_mutex_lock(&dcl_lock); |
list_remove(&devcon->link); |
fibril_mutex_unlock(&dcl_lock); |
} |
int block_init(dev_handle_t dev_handle, size_t com_size) |
{ |
int rc; |
int dev_phone; |
void *com_area; |
com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!com_area) { |
return ENOMEM; |
} |
dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING); |
if (dev_phone < 0) { |
munmap(com_area, com_size); |
return dev_phone; |
} |
rc = ipc_share_out_start(dev_phone, com_area, |
AS_AREA_READ | AS_AREA_WRITE); |
if (rc != EOK) { |
munmap(com_area, com_size); |
ipc_hangup(dev_phone); |
return rc; |
} |
rc = devcon_add(dev_handle, dev_phone, com_area, com_size); |
if (rc != EOK) { |
munmap(com_area, com_size); |
ipc_hangup(dev_phone); |
return rc; |
} |
return EOK; |
} |
void block_fini(dev_handle_t dev_handle) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
devcon_remove(devcon); |
if (devcon->bb_buf) |
free(devcon->bb_buf); |
if (devcon->cache) { |
hash_table_destroy(&devcon->cache->block_hash); |
free(devcon->cache); |
} |
munmap(devcon->com_area, devcon->com_size); |
ipc_hangup(devcon->dev_phone); |
free(devcon); |
} |
int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size) |
{ |
void *bb_buf; |
int rc; |
devcon_t *devcon = devcon_search(dev_handle); |
if (!devcon) |
return ENOENT; |
if (devcon->bb_buf) |
return EEXIST; |
bb_buf = malloc(size); |
if (!bb_buf) |
return ENOMEM; |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, 0, size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
free(bb_buf); |
return rc; |
} |
memcpy(bb_buf, devcon->com_area, size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
devcon->bb_buf = bb_buf; |
devcon->bb_off = off; |
devcon->bb_size = size; |
return EOK; |
} |
void *block_bb_get(dev_handle_t dev_handle) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
return devcon->bb_buf; |
} |
static hash_index_t cache_hash(unsigned long *key) |
{ |
return *key & (CACHE_BUCKETS - 1); |
} |
static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) |
{ |
block_t *b = hash_table_get_instance(item, block_t, hash_link); |
return b->boff == *key; |
} |
static void cache_remove_callback(link_t *item) |
{ |
} |
static hash_table_operations_t cache_ops = { |
.hash = cache_hash, |
.compare = cache_compare, |
.remove_callback = cache_remove_callback |
}; |
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks, |
enum cache_mode mode) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
cache_t *cache; |
if (!devcon) |
return ENOENT; |
if (devcon->cache) |
return EEXIST; |
cache = malloc(sizeof(cache_t)); |
if (!cache) |
return ENOMEM; |
fibril_mutex_initialize(&cache->lock); |
list_initialize(&cache->free_head); |
cache->block_size = size; |
cache->block_count = blocks; |
cache->blocks_cached = 0; |
cache->mode = mode; |
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, |
&cache_ops)) { |
free(cache); |
return ENOMEM; |
} |
devcon->cache = cache; |
return EOK; |
} |
#define CACHE_LO_WATERMARK 10 |
#define CACHE_HI_WATERMARK 20 |
static bool cache_can_grow(cache_t *cache) |
{ |
if (cache->blocks_cached < CACHE_LO_WATERMARK) |
return true; |
if (!list_empty(&cache->free_head)) |
return false; |
return true; |
} |
static void block_initialize(block_t *b) |
{ |
fibril_mutex_initialize(&b->lock); |
b->refcnt = 1; |
b->dirty = false; |
fibril_rwlock_initialize(&b->contents_lock); |
link_initialize(&b->free_link); |
link_initialize(&b->hash_link); |
} |
/** Instantiate a block in memory and get a reference to it. |
* |
* @param dev_handle Device handle of the block device. |
* @param boff Block offset. |
* @param flags If BLOCK_FLAGS_NOREAD is specified, block_get() |
* will not read the contents of the block from the |
* device. |
* |
* @return Block structure. |
*/ |
block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags) |
{ |
devcon_t *devcon; |
cache_t *cache; |
block_t *b; |
link_t *l; |
unsigned long key = boff; |
bn_t oboff; |
devcon = devcon_search(dev_handle); |
assert(devcon); |
assert(devcon->cache); |
cache = devcon->cache; |
fibril_mutex_lock(&cache->lock); |
l = hash_table_find(&cache->block_hash, &key); |
if (l) { |
/* |
* We found the block in the cache. |
*/ |
b = hash_table_get_instance(l, block_t, hash_link); |
fibril_mutex_lock(&b->lock); |
if (b->refcnt++ == 0) |
list_remove(&b->free_link); |
fibril_mutex_unlock(&b->lock); |
fibril_mutex_unlock(&cache->lock); |
} else { |
/* |
* The block was not found in the cache. |
*/ |
int rc; |
bool sync = false; |
if (cache_can_grow(cache)) { |
/* |
* We can grow the cache by allocating new blocks. |
* Should the allocation fail, we fail over and try to |
* recycle a block from the cache. |
*/ |
b = malloc(sizeof(block_t)); |
if (!b) |
goto recycle; |
b->data = malloc(cache->block_size); |
if (!b->data) { |
free(b); |
goto recycle; |
} |
cache->blocks_cached++; |
} else { |
/* |
* Try to recycle a block from the free list. |
*/ |
unsigned long temp_key; |
recycle: |
assert(!list_empty(&cache->free_head)); |
l = cache->free_head.next; |
list_remove(l); |
b = list_get_instance(l, block_t, free_link); |
sync = b->dirty; |
oboff = b->boff; |
temp_key = b->boff; |
hash_table_remove(&cache->block_hash, &temp_key, 1); |
} |
block_initialize(b); |
b->dev_handle = dev_handle; |
b->size = cache->block_size; |
b->boff = boff; |
hash_table_insert(&cache->block_hash, &key, &b->hash_link); |
/* |
* Lock the block before releasing the cache lock. Thus we don't |
* kill concurent operations on the cache while doing I/O on the |
* block. |
*/ |
fibril_mutex_lock(&b->lock); |
fibril_mutex_unlock(&cache->lock); |
if (sync) { |
/* |
* The block is dirty and needs to be written back to |
* the device before we can read in the new contents. |
*/ |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, b->data, b->size); |
rc = write_block(devcon, oboff, cache->block_size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
if (!(flags & BLOCK_FLAGS_NOREAD)) { |
/* |
* The block contains old or no data. We need to read |
* the new contents from the device. |
*/ |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, b->boff, cache->block_size); |
assert(rc == EOK); |
memcpy(b->data, devcon->com_area, cache->block_size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
fibril_mutex_unlock(&b->lock); |
} |
return b; |
} |
/** Release a reference to a block. |
* |
* If the last reference is dropped, the block is put on the free list. |
* |
* @param block Block of which a reference is to be released. |
*/ |
void block_put(block_t *block) |
{ |
devcon_t *devcon = devcon_search(block->dev_handle); |
cache_t *cache; |
int rc; |
assert(devcon); |
assert(devcon->cache); |
cache = devcon->cache; |
fibril_mutex_lock(&cache->lock); |
fibril_mutex_lock(&block->lock); |
if (!--block->refcnt) { |
/* |
* Last reference to the block was dropped. Either free the |
* block or put it on the free list. |
*/ |
if (cache->blocks_cached > CACHE_HI_WATERMARK) { |
/* |
* Currently there are too many cached blocks. |
*/ |
if (block->dirty) { |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, |
block->size); |
rc = write_block(devcon, block->boff, |
block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
/* |
* Take the block out of the cache and free it. |
*/ |
unsigned long key = block->boff; |
hash_table_remove(&cache->block_hash, &key, 1); |
free(block); |
free(block->data); |
cache->blocks_cached--; |
fibril_mutex_unlock(&cache->lock); |
return; |
} |
/* |
* Put the block on the free list. |
*/ |
list_append(&block->free_link, &cache->free_head); |
if (cache->mode != CACHE_MODE_WB && block->dirty) { |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, block->size); |
rc = write_block(devcon, block->boff, block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
block->dirty = false; |
} |
} |
fibril_mutex_unlock(&block->lock); |
fibril_mutex_unlock(&cache->lock); |
} |
/** Read sequential data from a block device. |
* |
* @param dev_handle Device handle of the block device. |
* @param bufpos Pointer to the first unread valid offset within the |
* communication buffer. |
* @param buflen Pointer to the number of unread bytes that are ready in |
* the communication buffer. |
* @param pos Device position to be read. |
* @param dst Destination buffer. |
* @param size Size of the destination buffer. |
* @param block_size Block size to be used for the transfer. |
* |
* @return EOK on success or a negative return code on failure. |
*/ |
int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen, |
off_t *pos, void *dst, size_t size, size_t block_size) |
{ |
off_t offset = 0; |
size_t left = size; |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
fibril_mutex_lock(&devcon->com_area_lock); |
while (left > 0) { |
size_t rd; |
if (*bufpos + left < *buflen) |
rd = left; |
else |
rd = *buflen - *bufpos; |
if (rd > 0) { |
/* |
* Copy the contents of the communication buffer to the |
* destination buffer. |
*/ |
memcpy(dst + offset, devcon->com_area + *bufpos, rd); |
offset += rd; |
*bufpos += rd; |
*pos += rd; |
left -= rd; |
} |
if (*bufpos == (off_t) *buflen) { |
/* Refill the communication buffer with a new block. */ |
int rc; |
rc = read_block(devcon, *pos / block_size, block_size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
return rc; |
} |
*bufpos = 0; |
*buflen = block_size; |
} |
} |
fibril_mutex_unlock(&devcon->com_area_lock); |
return EOK; |
} |
/** Read block from block device. |
* |
* @param devcon Device connection. |
* @param boff Block index. |
* @param block_size Block size. |
* @param src Buffer for storing the data. |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
return EOK; |
} |
/** Write block to block device. |
* |
* @param devcon Device connection. |
* @param boff Block index. |
* @param block_size Block size. |
* @param src Buffer containing the data to write. |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
return EOK; |
} |
/** @} |
*/ |
/branches/arm/uspace/lib/libblock/libblock.h |
---|
0,0 → 1,113 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libblock |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef LIBBLOCK_LIBBLOCK_H_ |
#define LIBBLOCK_LIBBLOCK_H_ |
#include <stdint.h> |
#include "../../srv/vfs/vfs.h" |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
/* |
* Flags that can be used with block_get(). |
*/ |
/** |
* This macro is a symbolic value for situations where no special flags are |
* needed. |
*/ |
#define BLOCK_FLAGS_NONE 0 |
/** |
* When the client of block_get() intends to overwrite the current contents of |
* the block, this flag is used to avoid the unnecessary read. |
*/ |
#define BLOCK_FLAGS_NOREAD 1 |
typedef unsigned bn_t; /**< Block number type. */ |
typedef struct block { |
/** Mutex protecting the reference count. */ |
fibril_mutex_t lock; |
/** Number of references to the block_t structure. */ |
unsigned refcnt; |
/** If true, the block needs to be written back to the block device. */ |
bool dirty; |
/** Readers / Writer lock protecting the contents of the block. */ |
fibril_rwlock_t contents_lock; |
/** Handle of the device where the block resides. */ |
dev_handle_t dev_handle; |
/** Block offset on the block device. Counted in 'size'-byte blocks. */ |
bn_t boff; |
/** Size of the block. */ |
size_t size; |
/** Link for placing the block into the free block list. */ |
link_t free_link; |
/** Link for placing the block into the block hash table. */ |
link_t hash_link; |
/** Buffer with the block data. */ |
void *data; |
} block_t; |
/** Caching mode */ |
enum cache_mode { |
/** Write-Through */ |
CACHE_MODE_WT, |
/** Write-Back */ |
CACHE_MODE_WB |
}; |
extern int block_init(dev_handle_t, size_t); |
extern void block_fini(dev_handle_t); |
extern int block_bb_read(dev_handle_t, off_t, size_t); |
extern void *block_bb_get(dev_handle_t); |
extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode); |
extern block_t *block_get(dev_handle_t, bn_t, int); |
extern void block_put(block_t *); |
extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libblock/Makefile |
---|
0,0 → 1,67 |
# |
# Copyright (c) 2005 Martin Decky |
# Copyright (c) 2007 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Common compiler flags |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -Iinclude |
## Sources |
# |
SOURCES = \ |
libblock.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend |
all: libblock.a |
-include Makefile.depend |
clean: |
-rm -f libblock.a Makefile.depend |
find . -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
libblock.a: depend $(OBJECTS) |
$(AR) rc libblock.a $(OBJECTS) |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/lib/libfs/libfs.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
36,7 → 36,6 |
#include "libfs.h" |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/rd/rd.h" |
#include <errno.h> |
#include <async.h> |
#include <ipc/ipc.h> |
43,6 → 42,8 |
#include <as.h> |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
#include <sys/stat.h> |
/** Register file system server. |
* |
69,7 → 70,7 |
* out-of-order, when it knows that the operation succeeded or failed. |
*/ |
ipc_call_t answer; |
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer); |
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); |
/* |
* Send our VFS info structure to VFS. |
104,7 → 105,7 |
} |
/* |
* Pick up the answer for the request to the VFS_REQUEST call. |
* Pick up the answer for the request to the VFS_IN_REQUEST call. |
*/ |
async_wait_for(req, NULL); |
reg->fs_handle = (int) IPC_GET_ARG1(answer); |
123,23 → 124,106 |
return IPC_GET_RETVAL(answer); |
} |
void fs_node_initialize(fs_node_t *fn) |
{ |
memset(fn, 0, sizeof(fs_node_t)); |
} |
void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
int res; |
ipcarg_t rc; |
ipc_call_t call; |
ipc_callid_t callid; |
/* accept the phone */ |
callid = async_get_call(&call); |
int mountee_phone = (int)IPC_GET_ARG1(call); |
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || |
mountee_phone < 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ |
res = ipc_data_write_receive(&callid, NULL); |
if (!res) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); |
if (!fn) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
if (fn->mp_data.mp_active) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, EBUSY); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); |
if (rc != 0) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, rc); |
ipc_answer_0(rid, rc); |
return; |
} |
ipc_call_t answer; |
aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle, |
&answer); |
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
if (rc == EOK) { |
fn->mp_data.mp_active = true; |
fn->mp_data.fs_handle = mr_fs_handle; |
fn->mp_data.dev_handle = mr_dev_handle; |
fn->mp_data.phone = mountee_phone; |
} |
/* |
* Do not release the FS node so that it stays in memory. |
*/ |
ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), |
IPC_GET_ARG3(answer)); |
} |
/** Lookup VFS triplet by name in the file system name space. |
* |
* The path passed in the PLB must be in the canonical file system path format |
* as returned by the canonify() function. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_OUT_LOOKUP request. |
* @param request VFS_OUT_LOOKUP request data itself. |
* |
*/ |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
unsigned next = IPC_GET_ARG1(*request); |
unsigned first = IPC_GET_ARG1(*request); |
unsigned last = IPC_GET_ARG2(*request); |
unsigned next = first; |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
int lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */ |
149,10 → 233,18 |
if (last < next) |
last += PLB_SIZE; |
void *par = NULL; |
void *cur = ops->root_get(dev_handle); |
void *tmp = NULL; |
fs_node_t *par = NULL; |
fs_node_t *cur = ops->root_get(dev_handle); |
fs_node_t *tmp = NULL; |
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP, |
next, last, cur->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
return; |
} |
if (ops->plb_get_char(next) == '/') |
next++; /* eat slash */ |
175,6 → 267,21 |
/* match the component */ |
tmp = ops->match(cur, component); |
if (tmp && tmp->mp_data.mp_active) { |
if (next > last) |
next = last = first; |
else |
next--; |
ipc_forward_slow(rid, tmp->mp_data.phone, |
VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, |
lflag, index, IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
ops->node_put(tmp); |
if (par) |
ops->node_put(par); |
return; |
} |
/* handle miss: match amongst siblings */ |
if (!tmp) { |
190,36 → 297,33 |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
void *nodep; |
fs_node_t *fn; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
fn = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, |
fn = ops->node_get(dev_handle, |
index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
if (fn) { |
int rc; |
rc = ops->link(cur, fn, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) { |
(void)ops->destroy( |
nodep); |
(void)ops->destroy(fn); |
} |
ipc_answer_0(rid, ENOSPC); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
goto out; |
} else if (lflag & L_PARENT) { |
/* return parent */ |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), |
ops->lnkcnt_get(cur)); |
} |
ipc_answer_0(rid, ENOENT); |
goto out; |
261,23 → 365,26 |
assert(len); |
component[len] = '\0'; |
void *nodep; |
fs_node_t *fn; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
fn = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
fn = ops->node_get(dev_handle, index); |
if (fn) { |
int rc; |
rc = ops->link(cur, fn, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) |
(void)ops->destroy(nodep); |
ipc_answer_0(rid, ENOSPC); |
(void)ops->destroy(fn); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
289,18 → 396,9 |
} |
/* handle hit */ |
if (lflag & L_PARENT) { |
ops->node_put(cur); |
cur = par; |
par = NULL; |
if (!cur) { |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
} |
if (lflag & L_UNLINK) { |
unsigned old_lnkcnt = ops->lnkcnt_get(cur); |
int res = ops->unlink(par, cur); |
int res = ops->unlink(par, cur, component); |
ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), old_lnkcnt); |
goto out; |
331,61 → 429,61 |
ops->node_put(tmp); |
} |
/** Read data from a block device. |
void libfs_stat(libfs_ops_t *ops, fs_handle_t fs_handle, 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); |
fs_node_t *fn = ops->node_get(dev_handle, index); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size) || |
size != sizeof(struct stat)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
struct stat stat; |
memset(&stat, 0, sizeof(struct stat)); |
stat.fs_handle = fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = ops->lnkcnt_get(fn); |
stat.is_file = ops->is_file(fn); |
stat.size = ops->size_get(fn); |
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
/** Open VFS triplet. |
* |
* @param phone Phone to be used to communicate with the device. |
* @param buffer Communication buffer shared with the device. |
* @param bufpos Pointer to the first unread valid offset within the |
* communication buffer. |
* @param buflen Pointer to the number of unread bytes that are ready in |
* the communication buffer. |
* @param pos Device position to be read. |
* @param dst Destination buffer. |
* @param size Size of the destination buffer. |
* @param block_size Block size to be used for the transfer. |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param rid Request ID of the VFS_OUT_OPEN_NODE request. |
* @param request VFS_OUT_OPEN_NODE request data itself. |
* |
* @return True on success, false on failure. |
*/ |
bool libfs_blockread(int phone, void *buffer, off_t *bufpos, size_t *buflen, |
off_t *pos, void *dst, size_t size, size_t block_size) |
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
off_t offset = 0; |
size_t left = size; |
dev_handle_t dev_handle = IPC_GET_ARG1(*request); |
fs_index_t index = IPC_GET_ARG2(*request); |
while (left > 0) { |
size_t rd; |
if (*bufpos + left < *buflen) |
rd = left; |
else |
rd = *buflen - *bufpos; |
if (rd > 0) { |
/* |
* Copy the contents of the communication buffer to the |
* destination buffer. |
*/ |
memcpy(dst + offset, buffer + *bufpos, rd); |
offset += rd; |
*bufpos += rd; |
*pos += rd; |
left -= rd; |
} |
if (*bufpos == *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(phone, RD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return false; |
*bufpos = 0; |
*buflen = block_size; |
} |
fs_node_t *node = ops->node_get(dev_handle, index); |
if (node == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
return true; |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, |
ops->size_get(node), ops->lnkcnt_get(node)); |
ops->node_put(node); |
} |
/** @} |
/branches/arm/uspace/lib/libfs/libfs.h |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2007 Jakub Jermar |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
26,54 → 26,69 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libfs |
/** @addtogroup libfs |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
#ifndef LIBFS_LIBFS_H_ |
#define LIBFS_LIBFS_H_ |
#define LIBFS_LIBFS_H_ |
#include "../../srv/vfs/vfs.h" |
#include <ipc/vfs.h> |
#include <stdint.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <devmap.h> |
typedef struct { |
void * (* match)(void *, const char *); |
void * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(void *); |
void * (* create)(int); |
int (* destroy)(void *); |
bool (* link)(void *, void *, const char *); |
int (* unlink)(void *, void *); |
fs_index_t (* index_get)(void *); |
size_t (* size_get)(void *); |
unsigned (* lnkcnt_get)(void *); |
bool (* has_children)(void *); |
void *(* root_get)(dev_handle_t); |
char (* plb_get_char)(unsigned pos); |
bool (* is_directory)(void *); |
bool (* is_file)(void *); |
bool mp_active; |
int phone; |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
} mp_data_t; |
typedef struct { |
mp_data_t mp_data; /**< Mount point info. */ |
void *data; /**< Data of the file system implementation. */ |
} fs_node_t; |
typedef struct { |
fs_node_t * (* match)(fs_node_t *, const char *); |
fs_node_t * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(fs_node_t *); |
fs_node_t * (* create)(dev_handle_t, int); |
int (* destroy)(fs_node_t *); |
int (* link)(fs_node_t *, fs_node_t *, const char *); |
int (* unlink)(fs_node_t *, fs_node_t *, const char *); |
fs_index_t (* index_get)(fs_node_t *); |
size_t (* size_get)(fs_node_t *); |
unsigned (* lnkcnt_get)(fs_node_t *); |
bool (* has_children)(fs_node_t *); |
fs_node_t *(* root_get)(dev_handle_t); |
char (* plb_get_char)(unsigned pos); |
bool (* is_directory)(fs_node_t *); |
bool (* is_file)(fs_node_t *); |
} libfs_ops_t; |
typedef struct { |
int fs_handle; /**< File system handle. */ |
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */ |
uint8_t *plb_ro; /**< Read-only PLB view. */ |
int fs_handle; /**< File system handle. */ |
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */ |
uint8_t *plb_ro; /**< Read-only PLB view. */ |
} fs_reg_t; |
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t); |
extern void fs_node_initialize(fs_node_t *); |
extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t, |
ipc_call_t *); |
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/lib/libfs/Makefile |
---|
31,6 → 31,7 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
57,7 → 58,7 |
find . -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
libfs.a: depend $(OBJECTS) |
$(AR) rc libfs.a $(OBJECTS) |
/branches/arm/uspace/lib/softfloat/include/sftypes.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup softfloat |
/** @addtogroup softfloat |
* @{ |
*/ |
/** @file |
41,40 → 41,40 |
typedef union { |
float f; |
uint32_t binary; |
struct { |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint32_t sign:1; |
uint32_t exp:8; |
uint32_t fraction:23; |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint32_t fraction:23; |
uint32_t exp:8; |
uint32_t sign:1; |
#else |
#error "Unknown endians." |
struct { |
#if defined(__BE__) |
uint32_t sign : 1; |
uint32_t exp : 8; |
uint32_t fraction : 23; |
#elif defined(__LE__) |
uint32_t fraction : 23; |
uint32_t exp : 8; |
uint32_t sign : 1; |
#else |
#error Unknown endianess |
#endif |
} parts __attribute__ ((packed)); |
} float32; |
} float32; |
typedef union { |
double d; |
uint64_t binary; |
struct { |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint64_t sign:1; |
uint64_t exp:11; |
uint64_t fraction:52; |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint64_t fraction:52; |
uint64_t exp:11; |
uint64_t sign:1; |
#else |
#error "Unknown endians." |
struct { |
#if defined(__BE__) |
uint64_t sign : 1; |
uint64_t exp : 11; |
uint64_t fraction : 52; |
#elif defined(__LE__) |
uint64_t fraction : 52; |
uint64_t exp : 11; |
uint64_t sign : 1; |
#else |
#error Unknown endianess |
#endif |
} parts __attribute__ ((packed)); |
} float64; |
} parts __attribute__ ((packed)); |
} float64; |
#define FLOAT32_MAX 0x7f800000 |
#define FLOAT32_MIN 0xff800000 |
109,7 → 109,5 |
#endif |
/** @} |
/** @} |
*/ |
/branches/arm/uspace/lib/softfloat/Makefile |
---|
30,25 → 30,26 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS +=-Iinclude -Iarch/$(ARCH)/include/ |
CFLAGS += -Iinclude -Iarch/$(UARCH)/include/ |
## Sources |
# |
GENERIC_SOURCES = \ |
generic/add.c \ |
generic/common.c \ |
generic/comparison.c \ |
generic/conversion.c \ |
generic/div.c \ |
generic/mul.c \ |
generic/other.c \ |
generic/softfloat.c \ |
GENERIC_SOURCES = \ |
generic/add.c \ |
generic/common.c \ |
generic/comparison.c \ |
generic/conversion.c \ |
generic/div.c \ |
generic/mul.c \ |
generic/other.c \ |
generic/softfloat.c \ |
generic/sub.c |
ARCH_SOURCES = |
66,7 → 67,7 |
find generic/ -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libsoftfloat.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libsoftfloat.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
/branches/arm/uspace/lib/softfloat/arch/ppc64/include/functions.h |
---|
File deleted |
/branches/arm/uspace/lib/softint/Makefile |
---|
30,6 → 30,7 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
58,7 → 59,7 |
find generic/ -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEMD_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libsoftint.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libsoftint.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
/branches/arm/uspace/srv/rd/rd.c |
---|
File deleted |
/branches/arm/uspace/srv/rd/rd.h |
---|
File deleted |
/branches/arm/uspace/srv/rd/Makefile |
---|
File deleted |
/branches/arm/uspace/srv/console/nameic.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/anim_4.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/anim_3.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/anim_2.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/anim_1.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/helenos.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/cons_selected.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/cons_idle.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/cons_kernel.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/cons_has_data.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/console.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
35,327 → 35,388 |
#include <libc.h> |
#include <fb.h> |
#include <ipc/ipc.h> |
#include <keys.h> |
#include <kbd.h> |
#include <io/keycode.h> |
#include <ipc/fb.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <key_buffer.h> |
#include <console.h> |
#include <keybuffer.h> |
#include <ipc/console.h> |
#include <unistd.h> |
#include <async.h> |
#include <libadt/fifo.h> |
#include <screenbuffer.h> |
#include <adt/fifo.h> |
#include <sys/mman.h> |
#include <stdio.h> |
#include <string.h> |
#include <sysinfo.h> |
#include <event.h> |
#include <devmap.h> |
#include <fibril_sync.h> |
#include "console.h" |
#include "gcons.h" |
#include "screenbuffer.h" |
#define MAX_KEYREQUESTS_BUFFERED 32 |
#define NAME "console" |
#define NAME "console" |
#define MAX_DEVICE_NAME 32 |
/** Index of currently used virtual console. |
*/ |
int active_console = 0; |
/** Phone to the keyboard driver. */ |
static int kbd_phone; |
/** Information about framebuffer |
*/ |
/** Information about framebuffer */ |
struct { |
int phone; /**< Framebuffer phone */ |
ipcarg_t rows; /**< Framebuffer rows */ |
ipcarg_t cols; /**< Framebuffer columns */ |
int phone; /**< Framebuffer phone */ |
ipcarg_t cols; /**< Framebuffer columns */ |
ipcarg_t rows; /**< Framebuffer rows */ |
int color_cap; /**< Color capabilities (FB_CCAP_xxx) */ |
} fb_info; |
typedef struct { |
keybuffer_t keybuffer; /**< Buffer for incoming keys. */ |
/** Buffer for unsatisfied request for keys. */ |
FIFO_CREATE_STATIC(keyrequests, ipc_callid_t, |
MAX_KEYREQUESTS_BUFFERED); |
int keyrequest_counter; /**< Number of requests in buffer. */ |
int client_phone; /**< Phone to connected client. */ |
int used; /**< 1 if this virtual console is |
* connected to some client.*/ |
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen |
* contents and related settings. */ |
} connection_t; |
size_t index; /**< Console index */ |
size_t refcount; /**< Connection reference count */ |
dev_handle_t dev_handle; /**< Device handle */ |
keybuffer_t keybuffer; /**< Buffer for incoming keys. */ |
screenbuffer_t scr; /**< Screenbuffer for saving screen |
contents and related settings. */ |
} console_t; |
static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual |
* consoles */ |
static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared |
* with framebufer used for |
* faster virtual console |
* switching */ |
/** Array of data for virtual consoles */ |
static console_t consoles[CONSOLE_COUNT]; |
static int kernel_pixmap = -1; /**< Number of fb pixmap, where kernel |
* console is stored */ |
static console_t *active_console = &consoles[0]; |
static console_t *prev_console = &consoles[0]; |
static console_t *kernel_console = &consoles[KERNEL_CONSOLE]; |
/** Pointer to memory shared with framebufer used for |
faster virtual console switching */ |
static keyfield_t *interbuffer = NULL; |
/** Find unused virtual console. |
* |
*/ |
static int find_free_connection(void) |
/** Information on row-span yet unsent to FB driver. */ |
struct { |
size_t col; /**< Leftmost column of the span. */ |
size_t row; /**< Row where the span lies. */ |
size_t cnt; /**< Width of the span. */ |
} fb_pending; |
static FIBRIL_MUTEX_INITIALIZE(input_mutex); |
static FIBRIL_CONDVAR_INITIALIZE(input_cv); |
static void curs_visibility(bool visible) |
{ |
int i; |
for (i = 0; i < CONSOLE_COUNT; i++) { |
if (!connections[i].used) |
return i; |
} |
return -1; |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); |
} |
static void clrscr(void) |
static void curs_hide_sync(void) |
{ |
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); |
} |
static void curs_goto(size_t x, size_t y) |
{ |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); |
} |
static void screen_clear(void) |
{ |
async_msg_0(fb_info.phone, FB_CLEAR); |
} |
static void curs_visibility(int v) |
static void screen_yield(void) |
{ |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, v); |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD); |
} |
static void curs_goto(int row, int col) |
static void screen_reclaim(void) |
{ |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM); |
} |
static void set_style(style_t *style) |
static void kbd_yield(void) |
{ |
async_msg_2(fb_info.phone, FB_SET_STYLE, style->fg_color, |
style->bg_color); |
ipc_call_sync_0_0(kbd_phone, KBD_YIELD); |
} |
static void set_style_col(int fgcolor, int bgcolor) |
static void kbd_reclaim(void) |
{ |
async_msg_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor); |
ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM); |
} |
static void prtchr(char c, int row, int col) |
static void set_style(int style) |
{ |
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col); |
async_msg_1(fb_info.phone, FB_SET_STYLE, style); |
} |
/** Check key and process special keys. |
static void set_color(int fgcolor, int bgcolor, int flags) |
{ |
async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); |
} |
static void set_rgb_color(int fgcolor, int bgcolor) |
{ |
async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); |
} |
static void set_attrs(attrs_t *attrs) |
{ |
switch (attrs->t) { |
case at_style: |
set_style(attrs->a.s.style); |
break; |
case at_idx: |
set_color(attrs->a.i.fg_color, attrs->a.i.bg_color, |
attrs->a.i.flags); |
break; |
case at_rgb: |
set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color); |
break; |
} |
} |
int ccap_fb_to_con(int ccap_fb, int *ccap_con) |
{ |
switch (ccap_fb) { |
case FB_CCAP_NONE: *ccap_con = CONSOLE_CCAP_NONE; break; |
case FB_CCAP_STYLE: *ccap_con = CONSOLE_CCAP_STYLE; break; |
case FB_CCAP_INDEXED: *ccap_con = CONSOLE_CCAP_INDEXED; break; |
case FB_CCAP_RGB: *ccap_con = CONSOLE_CCAP_RGB; break; |
default: return EINVAL; |
} |
return EOK; |
} |
/** Send an area of screenbuffer to the FB driver. */ |
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height) |
{ |
if (interbuffer) { |
ipcarg_t x; |
ipcarg_t y; |
for (y = 0; y < height; y++) { |
for (x = 0; x < width; x++) { |
interbuffer[y * width + x] = |
*get_field_at(&cons->scr, x0 + x, y0 + y); |
} |
} |
async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, |
x0, y0, width, height); |
} |
} |
/** Flush pending cells to FB. */ |
static void fb_pending_flush(void) |
{ |
if (fb_pending.cnt > 0) { |
fb_update_area(active_console, fb_pending.col, |
fb_pending.row, fb_pending.cnt, 1); |
fb_pending.cnt = 0; |
} |
} |
/** Mark a character cell as changed. |
* |
* This adds the cell to the pending rowspan if possible. Otherwise |
* the old span is flushed first. |
* |
*/ |
static void write_char(int console, char key) |
static void cell_mark_changed(size_t col, size_t row) |
{ |
screenbuffer_t *scr = &(connections[console].screenbuffer); |
if (fb_pending.cnt != 0) { |
if ((col != fb_pending.col + fb_pending.cnt) |
|| (row != fb_pending.row)) { |
fb_pending_flush(); |
} |
} |
switch (key) { |
if (fb_pending.cnt == 0) { |
fb_pending.col = col; |
fb_pending.row = row; |
} |
fb_pending.cnt++; |
} |
/** Print a character to the active VC with buffering. */ |
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row) |
{ |
async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); |
} |
/** Process a character from the client (TTY emulation). */ |
static void write_char(console_t *cons, wchar_t ch) |
{ |
bool flush_cursor = false; |
switch (ch) { |
case '\n': |
scr->position_y++; |
scr->position_x = 0; |
fb_pending_flush(); |
flush_cursor = true; |
cons->scr.position_y++; |
cons->scr.position_x = 0; |
break; |
case '\r': |
break; |
case '\t': |
scr->position_x += 8; |
scr->position_x -= scr->position_x % 8; |
cons->scr.position_x += 8; |
cons->scr.position_x -= cons->scr.position_x % 8; |
break; |
case '\b': |
if (scr->position_x == 0) |
if (cons->scr.position_x == 0) |
break; |
scr->position_x--; |
if (console == active_console) |
prtchr(' ', scr->position_y, scr->position_x); |
screenbuffer_putchar(scr, ' '); |
cons->scr.position_x--; |
if (cons == active_console) |
cell_mark_changed(cons->scr.position_x, cons->scr.position_y); |
screenbuffer_putchar(&cons->scr, ' '); |
break; |
default: |
if (console == active_console) |
prtchr(key, scr->position_y, scr->position_x); |
screenbuffer_putchar(scr, key); |
scr->position_x++; |
default: |
if (cons == active_console) |
cell_mark_changed(cons->scr.position_x, cons->scr.position_y); |
screenbuffer_putchar(&cons->scr, ch); |
cons->scr.position_x++; |
} |
scr->position_y += (scr->position_x >= scr->size_x); |
if (cons->scr.position_x >= cons->scr.size_x) { |
flush_cursor = true; |
cons->scr.position_y++; |
} |
if (scr->position_y >= scr->size_y) { |
scr->position_y = scr->size_y - 1; |
screenbuffer_clear_line(scr, scr->top_line); |
scr->top_line = (scr->top_line + 1) % scr->size_y; |
if (console == active_console) |
if (cons->scr.position_y >= cons->scr.size_y) { |
fb_pending_flush(); |
cons->scr.position_y = cons->scr.size_y - 1; |
screenbuffer_clear_line(&cons->scr, cons->scr.top_line); |
cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y; |
if (cons == active_console) |
async_msg_1(fb_info.phone, FB_SCROLL, 1); |
} |
scr->position_x = scr->position_x % scr->size_x; |
if (console == active_console) |
curs_goto(scr->position_y, scr->position_x); |
} |
/** Save current screen to pixmap, draw old pixmap |
* |
* @param oldpixmap Old pixmap |
* @return ID of pixmap of current screen |
*/ |
static int switch_screens(int oldpixmap) |
{ |
int newpmap; |
/* Save screen */ |
newpmap = async_req_0_0(fb_info.phone, FB_VP2PIXMAP); |
if (newpmap < 0) |
return -1; |
if (oldpixmap != -1) { |
/* Show old screen */ |
async_msg_2(fb_info.phone, FB_VP_DRAW_PIXMAP, 0, oldpixmap); |
/* Drop old pixmap */ |
async_msg_1(fb_info.phone, FB_DROP_PIXMAP, oldpixmap); |
} |
return newpmap; |
if (cons == active_console && flush_cursor) |
curs_goto(cons->scr.position_x, cons->scr.position_y); |
cons->scr.position_x = cons->scr.position_x % cons->scr.size_x; |
} |
/** Switch to new console */ |
static void change_console(int newcons) |
static void change_console(console_t *cons) |
{ |
connection_t *conn; |
static int console_pixmap = -1; |
int i, j, rc; |
keyfield_t *field; |
style_t *style; |
if (newcons == active_console) |
if (cons == active_console) |
return; |
if (newcons == KERNEL_CONSOLE) { |
if (active_console == KERNEL_CONSOLE) |
return; |
active_console = KERNEL_CONSOLE; |
curs_visibility(0); |
fb_pending_flush(); |
if (cons == kernel_console) { |
async_serialize_start(); |
if (kernel_pixmap == -1) { |
/* store/restore unsupported */ |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
} else { |
gcons_in_kernel(); |
console_pixmap = switch_screens(kernel_pixmap); |
kernel_pixmap = -1; |
} |
curs_hide_sync(); |
gcons_in_kernel(); |
screen_yield(); |
kbd_yield(); |
async_serialize_end(); |
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
return; |
} |
async_serialize_start(); |
if (console_pixmap != -1) { |
kernel_pixmap = switch_screens(console_pixmap); |
console_pixmap = -1; |
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { |
prev_console = active_console; |
active_console = kernel_console; |
} else |
cons = active_console; |
} |
active_console = newcons; |
gcons_change_console(newcons); |
conn = &connections[active_console]; |
set_style(&conn->screenbuffer.style); |
curs_visibility(0); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
unsigned int size_x; |
size_x = conn->screenbuffer.size_x; |
interbuffer[i + j * size_x] = |
*get_field_at(&conn->screenbuffer, i, j); |
} |
/* This call can preempt, but we are already at the end */ |
rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA); |
} |
if ((!interbuffer) || (rc != 0)) { |
set_style(&conn->screenbuffer.style); |
clrscr(); |
style = &conn->screenbuffer.style; |
for (j = 0; j < conn->screenbuffer.size_y; j++) |
for (i = 0; i < conn->screenbuffer.size_x; i++) { |
field = get_field_at(&conn->screenbuffer, i, j); |
if (!style_same(*style, field->style)) |
set_style(&field->style); |
style = &field->style; |
if ((field->character == ' ') && |
(style_same(field->style, |
conn->screenbuffer.style))) |
continue; |
prtchr(field->character, j, i); |
if (cons != kernel_console) { |
size_t x; |
size_t y; |
int rc = 0; |
async_serialize_start(); |
if (active_console == kernel_console) { |
screen_reclaim(); |
kbd_reclaim(); |
gcons_redraw_console(); |
} |
active_console = cons; |
gcons_change_console(cons->index); |
set_attrs(&cons->scr.attrs); |
curs_visibility(false); |
if (interbuffer) { |
for (y = 0; y < cons->scr.size_y; y++) { |
for (x = 0; x < cons->scr.size_x; x++) { |
interbuffer[y * cons->scr.size_x + x] = |
*get_field_at(&cons->scr, x, y); |
} |
} |
/* This call can preempt, but we are already at the end */ |
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, |
0, 0, cons->scr.size_x, |
cons->scr.size_y); |
} |
if ((!interbuffer) || (rc != 0)) { |
set_attrs(&cons->scr.attrs); |
screen_clear(); |
for (y = 0; y < cons->scr.size_y; y++) |
for (x = 0; x < cons->scr.size_x; x++) { |
keyfield_t *field = get_field_at(&cons->scr, x, y); |
if (!attrs_same(cons->scr.attrs, field->attrs)) |
set_attrs(&field->attrs); |
cons->scr.attrs = field->attrs; |
if ((field->character == ' ') && |
(attrs_same(field->attrs, cons->scr.attrs))) |
continue; |
fb_putchar(field->character, x, y); |
} |
} |
curs_goto(cons->scr.position_x, cons->scr.position_y); |
curs_visibility(cons->scr.is_cursor_visible); |
async_serialize_end(); |
} |
curs_goto(conn->screenbuffer.position_y, |
conn->screenbuffer.position_x); |
curs_visibility(conn->screenbuffer.is_cursor_visible); |
async_serialize_end(); |
} |
/** Handler for keyboard */ |
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
int c; |
connection_t *conn; |
int newcon; |
/* Ignore parameters, the connection is alread opened */ |
while (1) { |
callid = async_get_call(&call); |
/* Ignore parameters, the connection is already opened */ |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
int retval; |
console_event_t ev; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
/* TODO: Handle hangup */ |
return; |
case KBD_MS_LEFT: |
newcon = gcons_mouse_btn(IPC_GET_ARG1(call)); |
if (newcon != -1) |
change_console(newcon); |
case KBD_EVENT: |
/* Got event from keyboard driver. */ |
retval = 0; |
break; |
case KBD_MS_MOVE: |
gcons_mouse_move(IPC_GET_ARG1(call), |
IPC_GET_ARG2(call)); |
retval = 0; |
break; |
case KBD_PUSHCHAR: |
/* got key from keyboard driver */ |
ev.type = IPC_GET_ARG1(call); |
ev.key = IPC_GET_ARG2(call); |
ev.mods = IPC_GET_ARG3(call); |
ev.c = IPC_GET_ARG4(call); |
retval = 0; |
c = IPC_GET_ARG1(call); |
/* switch to another virtual console */ |
conn = &connections[active_console]; |
/* |
* if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + |
* CONSOLE_COUNT)) { |
*/ |
if ((c >= 0x101) && (c < 0x101 + CONSOLE_COUNT)) { |
if (c == 0x112) |
change_console(KERNEL_CONSOLE); |
if ((ev.key >= KC_F1) && (ev.key < KC_F1 + |
CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) { |
if (ev.key == KC_F1 + KERNEL_CONSOLE) |
change_console(kernel_console); |
else |
change_console(c - 0x101); |
change_console(&consoles[ev.key - KC_F1]); |
break; |
} |
/* if client is awaiting key, send it */ |
if (conn->keyrequest_counter > 0) { |
conn->keyrequest_counter--; |
ipc_answer_1(fifo_pop(conn->keyrequests), EOK, |
c); |
break; |
} |
keybuffer_push(&conn->keybuffer, c); |
retval = 0; |
fibril_mutex_lock(&input_mutex); |
keybuffer_push(&active_console->keybuffer, &ev); |
fibril_condvar_broadcast(&input_cv); |
fibril_mutex_unlock(&input_mutex); |
break; |
default: |
retval = ENOENT; |
364,204 → 425,361 |
} |
} |
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *buf = (char *) malloc(size); |
if (buf == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
(void) ipc_data_write_finalize(callid, buf, size); |
async_serialize_start(); |
size_t off = 0; |
while (off < size) { |
wchar_t ch = str_decode(buf, &off, size); |
write_char(cons, ch); |
} |
async_serialize_end(); |
gcons_notify_char(cons->index); |
ipc_answer_1(rid, EOK, size); |
free(buf); |
} |
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *buf = (char *) malloc(size); |
if (buf == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
size_t pos = 0; |
console_event_t ev; |
fibril_mutex_lock(&input_mutex); |
recheck: |
while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) { |
if (ev.type == KEY_PRESS) { |
buf[pos] = ev.c; |
pos++; |
} |
} |
if (pos == size) { |
(void) ipc_data_read_finalize(callid, buf, size); |
ipc_answer_1(rid, EOK, size); |
free(buf); |
} else { |
fibril_condvar_wait(&input_cv, &input_mutex); |
goto recheck; |
} |
fibril_mutex_unlock(&input_mutex); |
} |
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) |
{ |
console_event_t ev; |
fibril_mutex_lock(&input_mutex); |
recheck: |
if (keybuffer_pop(&cons->keybuffer, &ev)) { |
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c); |
} else { |
fibril_condvar_wait(&input_cv, &input_mutex); |
goto recheck; |
} |
fibril_mutex_unlock(&input_mutex); |
} |
/** Default thread for new connections */ |
static void client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
console_t *cons = NULL; |
size_t i; |
for (i = 0; i < CONSOLE_COUNT; i++) { |
if (i == KERNEL_CONSOLE) |
continue; |
if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) { |
cons = &consoles[i]; |
break; |
} |
} |
if (cons == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
ipc_call_t call; |
int consnum; |
ipcarg_t arg1, arg2; |
connection_t *conn; |
ipcarg_t arg1; |
ipcarg_t arg2; |
ipcarg_t arg3; |
if ((consnum = find_free_connection()) == -1) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
conn = &connections[consnum]; |
conn->used = 1; |
int cons_ccap; |
int rc; |
async_serialize_start(); |
gcons_notify_connect(consnum); |
conn->client_phone = IPC_GET_ARG5(*icall); |
screenbuffer_clear(&conn->screenbuffer); |
if (cons->refcount == 0) |
gcons_notify_connect(cons->index); |
cons->refcount++; |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
while (1) { |
while (true) { |
async_serialize_end(); |
callid = async_get_call(&call); |
async_serialize_start(); |
arg1 = 0; |
arg2 = 0; |
arg3 = 0; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
gcons_notify_disconnect(consnum); |
/* Answer all pending requests */ |
while (conn->keyrequest_counter > 0) { |
conn->keyrequest_counter--; |
ipc_answer_0(fifo_pop(conn->keyrequests), |
ENOENT); |
break; |
cons->refcount--; |
if (cons->refcount == 0) |
gcons_notify_disconnect(cons->index); |
return; |
case VFS_OUT_READ: |
async_serialize_end(); |
cons_read(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_OUT_WRITE: |
async_serialize_end(); |
cons_write(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_OUT_SYNC: |
fb_pending_flush(); |
if (cons == active_console) { |
async_req_0_0(fb_info.phone, FB_FLUSH); |
curs_goto(cons->scr.position_x, cons->scr.position_y); |
} |
conn->used = 0; |
return; |
case CONSOLE_PUTCHAR: |
write_char(consnum, IPC_GET_ARG1(call)); |
gcons_notify_char(consnum); |
break; |
case CONSOLE_CLEAR: |
/* Send message to fb */ |
if (consnum == active_console) { |
async_msg_0(fb_info.phone, FB_CLEAR); |
} |
if (cons == active_console) |
async_msg_0(fb_info.phone, FB_CLEAR); |
screenbuffer_clear(&conn->screenbuffer); |
screenbuffer_clear(&cons->scr); |
break; |
case CONSOLE_GOTO: |
screenbuffer_goto(&conn->screenbuffer, |
IPC_GET_ARG2(call), IPC_GET_ARG1(call)); |
if (consnum == active_console) |
screenbuffer_goto(&cons->scr, |
IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
if (cons == active_console) |
curs_goto(IPC_GET_ARG1(call), |
IPC_GET_ARG2(call)); |
break; |
case CONSOLE_GETSIZE: |
arg1 = fb_info.rows; |
arg2 = fb_info.cols; |
case CONSOLE_GET_SIZE: |
arg1 = fb_info.cols; |
arg2 = fb_info.rows; |
break; |
case CONSOLE_FLUSH: |
if (consnum == active_console) |
async_req_0_0(fb_info.phone, FB_FLUSH); |
case CONSOLE_GET_COLOR_CAP: |
rc = ccap_fb_to_con(fb_info.color_cap, &cons_ccap); |
if (rc != EOK) { |
ipc_answer_0(callid, rc); |
continue; |
} |
arg1 = cons_ccap; |
break; |
case CONSOLE_SET_STYLE: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
screenbuffer_set_style(&cons->scr, arg1); |
if (cons == active_console) |
set_style(arg1); |
break; |
case CONSOLE_SET_COLOR: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_style(&conn->screenbuffer, arg1, |
arg2); |
if (consnum == active_console) |
set_style_col(arg1, arg2); |
arg3 = IPC_GET_ARG3(call); |
screenbuffer_set_color(&cons->scr, arg1, arg2, arg3); |
if (cons == active_console) |
set_color(arg1, arg2, arg3); |
break; |
case CONSOLE_SET_RGB_COLOR: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_rgb_color(&cons->scr, arg1, arg2); |
if (cons == active_console) |
set_rgb_color(arg1, arg2); |
break; |
case CONSOLE_CURSOR_VISIBILITY: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
conn->screenbuffer.is_cursor_visible = arg1; |
if (consnum == active_console) |
cons->scr.is_cursor_visible = arg1; |
if (cons == active_console) |
curs_visibility(arg1); |
break; |
case CONSOLE_GETCHAR: |
if (keybuffer_empty(&conn->keybuffer)) { |
/* buffer is empty -> store request */ |
if (conn->keyrequest_counter < |
MAX_KEYREQUESTS_BUFFERED) { |
fifo_push(conn->keyrequests, callid); |
conn->keyrequest_counter++; |
} else { |
/* |
* No key available and too many |
* requests => fail. |
*/ |
ipc_answer_0(callid, ELIMIT); |
} |
continue; |
} |
keybuffer_pop(&conn->keybuffer, (int *) &arg1); |
case CONSOLE_GET_EVENT: |
async_serialize_end(); |
cons_get_event(cons, callid, &call); |
async_serialize_start(); |
continue; |
case CONSOLE_KCON_ENABLE: |
change_console(kernel_console); |
break; |
} |
ipc_answer_2(callid, EOK, arg1, arg2); |
ipc_answer_3(callid, EOK, arg1, arg2, arg3); |
} |
} |
int main(int argc, char *argv[]) |
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
printf(NAME ": HelenOS Console service\n"); |
ipcarg_t phonehash; |
int kbd_phone; |
int i; |
change_console(prev_console); |
} |
async_set_client_connection(client_connection); |
static bool console_init(void) |
{ |
ipcarg_t color_cap; |
/* Connect to keyboard driver */ |
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
while (kbd_phone < 0) { |
usleep(10000); |
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
if (kbd_phone < 0) { |
printf(NAME ": Failed to connect to keyboard service\n"); |
return false; |
} |
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
return -1; |
ipcarg_t phonehash; |
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { |
printf(NAME ": Failed to create callback from keyboard service\n"); |
return false; |
} |
async_new_connection(phonehash, 0, NULL, keyboard_events); |
/* Connect to framebuffer driver */ |
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0); |
if (fb_info.phone < 0) { |
printf(NAME ": Failed to connect to video service\n"); |
return -1; |
} |
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0); |
while (fb_info.phone < 0) { |
usleep(10000); |
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0); |
/* Register driver */ |
int rc = devmap_driver_register(NAME, client_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver (%d)\n", rc); |
return false; |
} |
/* Save old kernel screen */ |
kernel_pixmap = switch_screens(-1); |
/* Initialize gcons */ |
gcons_init(fb_info.phone); |
/* Synchronize, the gcons can have something in queue */ |
/* Synchronize, the gcons could put something in queue */ |
async_req_0_0(fb_info.phone, FB_FLUSH); |
/* Enable double buffering */ |
async_msg_2(fb_info.phone, FB_VIEWPORT_DB, (sysarg_t) -1, 1); |
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows); |
async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &color_cap); |
fb_info.color_cap = color_cap; |
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows, |
&fb_info.cols); |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
/* Set up shared memory buffer. */ |
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; |
interbuffer = as_get_mappable_page(ib_size); |
/* Init virtual consoles */ |
for (i = 0; i < CONSOLE_COUNT; i++) { |
connections[i].used = 0; |
keybuffer_init(&connections[i].keybuffer); |
connections[i].keyrequests.head = 0; |
connections[i].keyrequests.tail = 0; |
connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED; |
connections[i].keyrequest_counter = 0; |
if (screenbuffer_init(&connections[i].screenbuffer, |
fb_info.cols, fb_info.rows) == NULL) { |
/* FIXME: handle error */ |
return -1; |
} |
} |
connections[KERNEL_CONSOLE].used = 1; |
if (as_area_create(interbuffer, ib_size, AS_AREA_READ | |
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) |
interbuffer = NULL; |
interbuffer = mmap(NULL, |
sizeof(keyfield_t) * fb_info.cols * fb_info.rows, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!interbuffer) { |
if (interbuffer) { |
if (ipc_share_out_start(fb_info.phone, interbuffer, |
AS_AREA_READ) != EOK) { |
munmap(interbuffer, |
sizeof(keyfield_t) * fb_info.cols * fb_info.rows); |
as_area_destroy(interbuffer); |
interbuffer = NULL; |
} |
} |
fb_pending.cnt = 0; |
/* Inititalize consoles */ |
size_t i; |
for (i = 0; i < CONSOLE_COUNT; i++) { |
if (i != KERNEL_CONSOLE) { |
if (screenbuffer_init(&consoles[i].scr, |
fb_info.cols, fb_info.rows) == NULL) { |
printf(NAME ": Unable to allocate screen buffer %u\n", i); |
return false; |
} |
screenbuffer_clear(&consoles[i].scr); |
keybuffer_init(&consoles[i].keybuffer); |
consoles[i].index = i; |
consoles[i].refcount = 0; |
char vc[MAX_DEVICE_NAME]; |
snprintf(vc, MAX_DEVICE_NAME, "vc%u", i); |
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s\n", vc); |
return false; |
} |
} |
} |
/* Disable kernel output to the console */ |
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE); |
/* Initialize the screen */ |
async_serialize_start(); |
gcons_redraw_console(); |
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
screen_clear(); |
curs_goto(0, 0); |
curs_visibility( |
connections[active_console].screenbuffer.is_cursor_visible); |
curs_visibility(active_console->scr.is_cursor_visible); |
async_serialize_end(); |
/* Receive kernel notifications */ |
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) |
printf(NAME ": Error registering kconsole notifications\n"); |
async_set_interrupt_received(interrupt_received); |
return true; |
} |
/* Register at NS */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Console service\n"); |
if (!console_init()) |
return -1; |
// FIXME: avoid connectiong to itself, keep using klog |
// printf(NAME ": Accepting connections\n"); |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
return 0; |
} |
return 0; |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/console/screenbuffer.h |
---|
27,74 → 27,133 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
#ifndef __SCREENBUFFER_H__ |
#define __SCREENBUFFER_H__ |
#ifndef SCREENBUFFER_H__ |
#define SCREENBUFFER_H__ |
#include <stdint.h> |
#include <sys/types.h> |
#include <bool.h> |
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */ |
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */ |
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */ |
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */ |
typedef struct { |
unsigned int bg_color; /**< background color */ |
unsigned int fg_color; /**< foreground color */ |
} style_t; |
uint8_t style; |
} attr_style_t; |
typedef struct { |
uint8_t fg_color; |
uint8_t bg_color; |
uint8_t flags; |
} attr_idx_t; |
typedef struct { |
uint32_t bg_color; /**< background color */ |
uint32_t fg_color; /**< foreground color */ |
} attr_rgb_t; |
typedef struct { |
enum { |
at_style, |
at_idx, |
at_rgb |
} t; |
union { |
attr_style_t s; |
attr_idx_t i; |
attr_rgb_t r; |
} a; |
} attrs_t; |
/** One field on screen. It contain one character and its attributes. */ |
typedef struct { |
char character; /**< Character itself */ |
style_t style; /**< Character`s attributes */ |
wchar_t character; /**< Character itself */ |
attrs_t attrs; /**< Character attributes */ |
} keyfield_t; |
/** Structure for buffering state of one virtual console. |
*/ |
typedef struct { |
keyfield_t *buffer; /**< Screen content - characters and its style. Used as cyclyc buffer. */ |
unsigned int size_x, size_y; /**< Number of columns and rows */ |
unsigned int position_x, position_y; /**< Coordinates of last printed character for determining cursor position */ |
style_t style; /**< Current style */ |
unsigned int top_line; /**< Points to buffer[][] line that will be printed at screen as the first line */ |
unsigned char is_cursor_visible; /**< Cursor state - default is visible */ |
keyfield_t *buffer; /**< Screen content - characters and |
their attributes (used as a circular buffer) */ |
size_t size_x; /**< Number of columns */ |
size_t size_y; /**< Number of rows */ |
/** Coordinates of last printed character for determining cursor position */ |
size_t position_x; |
size_t position_y; |
attrs_t attrs; /**< Current attributes. */ |
size_t top_line; /**< Points to buffer[][] line that will |
be printed at screen as the first line */ |
bool is_cursor_visible; /**< Cursor state - default is visible */ |
} screenbuffer_t; |
/** Returns keyfield for position on screen. Screenbuffer->buffer is cyclic buffer so we must couted in index of the topmost line. |
* @param scr screenbuffer |
* @param x position on screen |
* @param y position on screen |
* @return keyfield structure with character and its attributes on x,y |
/** Returns keyfield for position on screen |
* |
* Screenbuffer->buffer is cyclic buffer so we |
* must couted in index of the topmost line. |
* |
* @param scr Screenbuffer |
* @param x Position on screen |
* @param y Position on screen |
* |
* @return Keyfield structure with character and its attributes on x, y |
* |
*/ |
static inline keyfield_t *get_field_at(screenbuffer_t *scr, unsigned int x, unsigned int y) |
static inline keyfield_t *get_field_at(screenbuffer_t *scr, size_t x, size_t y) |
{ |
return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x; |
} |
/** Compares two styles. |
* @param s1 first style |
* @param s2 second style |
* @return nonzero on equality |
/** Compares two sets of attributes. |
* |
* @param s1 First style |
* @param s2 Second style |
* |
* @return Nonzero on equality |
* |
*/ |
static inline int style_same(style_t s1, style_t s2) |
static inline int attrs_same(attrs_t a1, attrs_t a2) |
{ |
return s1.fg_color == s2.fg_color && s1.bg_color == s2.bg_color; |
if (a1.t != a2.t) |
return 0; |
switch (a1.t) { |
case at_style: |
return (a1.a.s.style == a2.a.s.style); |
case at_idx: |
return (a1.a.i.fg_color == a2.a.i.fg_color) |
&& (a1.a.i.bg_color == a2.a.i.bg_color) |
&& (a1.a.i.flags == a2.a.i.flags); |
case at_rgb: |
return (a1.a.r.fg_color == a2.a.r.fg_color) |
&& (a1.a.r.bg_color == a2.a.r.bg_color); |
} |
return 0; |
} |
void screenbuffer_putchar(screenbuffer_t *scr, char c); |
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y); |
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t c); |
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y); |
void screenbuffer_clear(screenbuffer_t *scr); |
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line); |
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line); |
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest); |
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y); |
void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color); |
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y); |
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style); |
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, |
uint8_t bg_color, uint8_t attr); |
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, |
uint32_t bg_color); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/console/gcons.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
39,23 → 39,25 |
#include <sys/mman.h> |
#include <string.h> |
#include <align.h> |
#include <bool.h> |
#include "console.h" |
#include "gcons.h" |
#define CONSOLE_TOP 66 |
#define CONSOLE_MARGIN 6 |
#define CONSOLE_TOP 66 |
#define CONSOLE_MARGIN 6 |
#define STATUS_START 110 |
#define STATUS_TOP 8 |
#define STATUS_SPACE 4 |
#define STATUS_WIDTH 48 |
#define STATUS_HEIGHT 48 |
#define STATUS_START 110 |
#define STATUS_TOP 8 |
#define STATUS_SPACE 4 |
#define STATUS_WIDTH 48 |
#define STATUS_HEIGHT 48 |
#define MAIN_COLOR 0xffffff |
#define MAIN_COLOR 0xffffff |
static int use_gcons = 0; |
static ipcarg_t xres,yres; |
static bool use_gcons = false; |
static ipcarg_t xres; |
static ipcarg_t yres; |
enum butstate { |
CONS_DISCONNECTED = 0, |
77,16 → 79,22 |
static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1}; |
static int animation = -1; |
static int active_console = 0; |
static size_t active_console = 0; |
size_t mouse_x; |
size_t mouse_y; |
bool btn_pressed; |
size_t btn_x; |
size_t btn_y; |
static void vp_switch(int vp) |
{ |
async_msg_1(fbphone,FB_VIEWPORT_SWITCH, vp); |
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp); |
} |
/** Create view port */ |
static int vp_create(unsigned int x, unsigned int y, unsigned int width, |
unsigned int height) |
static int vp_create(size_t x, size_t y, size_t width, size_t height) |
{ |
return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y, |
(width << 16) | height); |
97,48 → 105,52 |
async_msg_0(fbphone, FB_CLEAR); |
} |
static void set_style(int fgcolor, int bgcolor) |
static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor) |
{ |
async_msg_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor); |
async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor); |
} |
/** Transparent putchar */ |
static void tran_putch(char c, int row, int col) |
static void tran_putch(wchar_t ch, size_t col, size_t row) |
{ |
async_msg_3(fbphone, FB_TRANS_PUTCHAR, c, row, col); |
async_msg_3(fbphone, FB_PUTCHAR, ch, col, row); |
} |
/** Redraw the button showing state of a given console */ |
static void redraw_state(int consnum) |
static void redraw_state(size_t index) |
{ |
char data[5]; |
int i; |
enum butstate state = console_state[consnum]; |
vp_switch(cstatus_vp[consnum]); |
vp_switch(cstatus_vp[index]); |
enum butstate state = console_state[index]; |
if (ic_pixmaps[state] != -1) |
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum], |
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index], |
ic_pixmaps[state]); |
if (state != CONS_DISCONNECTED && state != CONS_KERNEL && |
state != CONS_DISCONNECTED_SEL) { |
snprintf(data, 5, "%d", consnum + 1); |
for (i = 0; data[i]; i++) |
tran_putch(data[i], 1, 2 + i); |
} |
if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL) |
&& (state != CONS_DISCONNECTED_SEL)) { |
char data[5]; |
snprintf(data, 5, "%u", index + 1); |
size_t i; |
for (i = 0; data[i] != 0; i++) |
tran_putch(data[i], 2 + i, 1); |
} |
} |
/** Notification run on changing console (except kernel console) */ |
void gcons_change_console(int consnum) |
void gcons_change_console(size_t index) |
{ |
int i; |
if (!use_gcons) |
return; |
if (active_console == KERNEL_CONSOLE) { |
size_t i; |
for (i = 0; i < CONSOLE_COUNT; i++) |
redraw_state(i); |
if (animation != -1) |
async_msg_1(fbphone, FB_ANIM_START, animation); |
} else { |
146,71 → 158,74 |
console_state[active_console] = CONS_DISCONNECTED; |
else |
console_state[active_console] = CONS_IDLE; |
redraw_state(active_console); |
} |
active_console = consnum; |
if (console_state[consnum] == CONS_DISCONNECTED) { |
console_state[consnum] = CONS_DISCONNECTED_SEL; |
redraw_state(consnum); |
} else |
console_state[consnum] = CONS_SELECTED; |
redraw_state(consnum); |
active_console = index; |
if ((console_state[index] == CONS_DISCONNECTED) |
|| (console_state[index] == CONS_DISCONNECTED_SEL)) |
console_state[index] = CONS_DISCONNECTED_SEL; |
else |
console_state[index] = CONS_SELECTED; |
redraw_state(index); |
vp_switch(console_vp); |
} |
/** Notification function that gets called on new output to virtual console */ |
void gcons_notify_char(int consnum) |
void gcons_notify_char(size_t index) |
{ |
if (!use_gcons) |
return; |
if (consnum == active_console || |
console_state[consnum] == CONS_HAS_DATA) |
if ((index == active_console) |
|| (console_state[index] == CONS_HAS_DATA)) |
return; |
console_state[consnum] = CONS_HAS_DATA; |
console_state[index] = CONS_HAS_DATA; |
if (active_console == KERNEL_CONSOLE) |
return; |
redraw_state(consnum); |
redraw_state(index); |
vp_switch(console_vp); |
} |
/** Notification function called on service disconnect from console */ |
void gcons_notify_disconnect(int consnum) |
void gcons_notify_disconnect(size_t index) |
{ |
if (!use_gcons) |
return; |
if (active_console == consnum) |
console_state[consnum] = CONS_DISCONNECTED_SEL; |
if (index == active_console) |
console_state[index] = CONS_DISCONNECTED_SEL; |
else |
console_state[consnum] = CONS_DISCONNECTED; |
console_state[index] = CONS_DISCONNECTED; |
if (active_console == KERNEL_CONSOLE) |
return; |
redraw_state(consnum); |
redraw_state(index); |
vp_switch(console_vp); |
} |
/** Notification function called on console connect */ |
void gcons_notify_connect(int consnum) |
void gcons_notify_connect(size_t index) |
{ |
if (!use_gcons) |
return; |
if (active_console == consnum) |
console_state[consnum] = CONS_SELECTED; |
if (index == active_console) |
console_state[index] = CONS_SELECTED; |
else |
console_state[consnum] = CONS_IDLE; |
console_state[index] = CONS_IDLE; |
if (active_console == KERNEL_CONSOLE) |
return; |
redraw_state(consnum); |
redraw_state(index); |
vp_switch(console_vp); |
} |
217,50 → 232,43 |
/** Change to kernel console */ |
void gcons_in_kernel(void) |
{ |
if (console_state[active_console] == CONS_DISCONNECTED_SEL) |
console_state[active_console] = CONS_DISCONNECTED; |
else |
console_state[active_console] = CONS_IDLE; |
redraw_state(active_console); |
if (animation != -1) |
async_msg_1(fbphone, FB_ANIM_STOP, animation); |
active_console = KERNEL_CONSOLE; /* Set to kernel console */ |
active_console = KERNEL_CONSOLE; |
vp_switch(0); |
} |
/** Return x, where left <= x <= right && |a-x|==min(|a-x|) is smallest */ |
static inline int limit(int a,int left, int right) |
/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */ |
static inline int limit(size_t a, size_t left, size_t right) |
{ |
if (a < left) |
a = left; |
if (a >= right) |
a = right - 1; |
return a; |
} |
int mouse_x, mouse_y; |
int btn_pressed, btn_x, btn_y; |
/** Handle mouse move |
* |
* @param dx Delta X of mouse move |
* @param dy Delta Y of mouse move |
*/ |
void gcons_mouse_move(int dx, int dy) |
void gcons_mouse_move(ssize_t dx, ssize_t dy) |
{ |
mouse_x = limit(mouse_x+dx, 0, xres); |
mouse_y = limit(mouse_y+dy, 0, yres); |
mouse_x = limit(mouse_x + dx, 0, xres); |
mouse_y = limit(mouse_y + dy, 0, yres); |
async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y); |
} |
static int gcons_find_conbut(int x, int y) |
{ |
int status_start = STATUS_START + (xres - 800) / 2;; |
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT) |
int status_start = STATUS_START + (xres - 800) / 2; |
if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT)) |
return -1; |
if (x < status_start) |
268,36 → 276,39 |
if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT) |
return -1; |
if (((x - status_start) % (STATUS_WIDTH+STATUS_SPACE)) < STATUS_SPACE) |
if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE) |
return -1; |
return (x - status_start) / (STATUS_WIDTH+STATUS_SPACE); |
return (x - status_start) / (STATUS_WIDTH + STATUS_SPACE); |
} |
/** Handle mouse click |
* |
* @param state New state (1-pressed, 0-depressed) |
* @param state New state (true - pressed, false - depressed) |
*/ |
int gcons_mouse_btn(int state) |
int gcons_mouse_btn(bool state) |
{ |
int conbut; |
if (state) { |
conbut = gcons_find_conbut(mouse_x, mouse_y); |
if (conbut != -1) { |
btn_pressed = 1; |
btn_pressed = true; |
btn_x = mouse_x; |
btn_y = mouse_y; |
} |
return -1; |
} |
if (!state && !btn_pressed) |
} |
if ((!state) && (!btn_pressed)) |
return -1; |
btn_pressed = 0; |
btn_pressed = false; |
conbut = gcons_find_conbut(mouse_x, mouse_y); |
if (conbut == gcons_find_conbut(btn_x, btn_y)) |
return conbut; |
return -1; |
} |
313,53 → 324,60 |
{ |
char *shm; |
int rc; |
/* Create area */ |
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | |
MAP_ANONYMOUS, 0, 0); |
if (shm == MAP_FAILED) |
return; |
memcpy(shm, logo, size); |
/* Send area */ |
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm); |
if (rc) |
goto exit; |
rc = ipc_share_out_start(fbphone, shm, PROTO_READ); |
if (rc) |
goto drop; |
/* Draw logo */ |
async_msg_2(fbphone, FB_DRAW_PPM, x, y); |
drop: |
/* Drop area */ |
async_msg_0(fbphone, FB_DROP_SHM); |
exit: |
exit: |
/* Remove area */ |
munmap(shm, size); |
} |
extern char _binary_helenos_ppm_start[0]; |
extern int _binary_helenos_ppm_size; |
extern char _binary_nameic_ppm_start[0]; |
extern int _binary_nameic_ppm_size; |
/** Redraws console graphics */ |
static void gcons_redraw_console(void) |
extern char _binary_gfx_helenos_ppm_start[0]; |
extern int _binary_gfx_helenos_ppm_size; |
extern char _binary_gfx_nameic_ppm_start[0]; |
extern int _binary_gfx_nameic_ppm_size; |
/** Redraws console graphics */ |
void gcons_redraw_console(void) |
{ |
int i; |
if (!use_gcons) |
return; |
vp_switch(0); |
set_style(MAIN_COLOR, MAIN_COLOR); |
set_rgb_color(MAIN_COLOR, MAIN_COLOR); |
clear(); |
draw_pixmap(_binary_helenos_ppm_start, |
(size_t) &_binary_helenos_ppm_size, xres - 66, 2); |
draw_pixmap(_binary_nameic_ppm_start, |
(size_t) &_binary_nameic_ppm_size, 5, 17); |
draw_pixmap(_binary_gfx_helenos_ppm_start, |
(size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2); |
draw_pixmap(_binary_gfx_nameic_ppm_start, |
(size_t) &_binary_gfx_nameic_ppm_size, 5, 17); |
for (i = 0; i < CONSOLE_COUNT; i++) |
redraw_state(i); |
vp_switch(console_vp); |
} |
367,152 → 385,159 |
* |
* @param data PPM data |
* @param size PPM data size |
* |
* @return Pixmap identification |
* |
*/ |
static int make_pixmap(char *data, int size) |
static int make_pixmap(char *data, size_t size) |
{ |
char *shm; |
int rc; |
int pxid = -1; |
/* Create area */ |
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | |
MAP_ANONYMOUS, 0, 0); |
if (shm == MAP_FAILED) |
return -1; |
memcpy(shm, data, size); |
/* Send area */ |
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm); |
if (rc) |
goto exit; |
rc = ipc_share_out_start(fbphone, shm, PROTO_READ); |
if (rc) |
goto drop; |
/* Obtain pixmap */ |
rc = async_req_0_0(fbphone, FB_SHM2PIXMAP); |
if (rc < 0) |
goto drop; |
pxid = rc; |
drop: |
/* Drop area */ |
async_msg_0(fbphone, FB_DROP_SHM); |
exit: |
exit: |
/* Remove area */ |
munmap(shm, size); |
return pxid; |
} |
extern char _binary_anim_1_ppm_start[0]; |
extern int _binary_anim_1_ppm_size; |
extern char _binary_anim_2_ppm_start[0]; |
extern int _binary_anim_2_ppm_size; |
extern char _binary_anim_3_ppm_start[0]; |
extern int _binary_anim_3_ppm_size; |
extern char _binary_anim_4_ppm_start[0]; |
extern int _binary_anim_4_ppm_size; |
extern char _binary_gfx_anim_1_ppm_start[0]; |
extern int _binary_gfx_anim_1_ppm_size; |
extern char _binary_gfx_anim_2_ppm_start[0]; |
extern int _binary_gfx_anim_2_ppm_size; |
extern char _binary_gfx_anim_3_ppm_start[0]; |
extern int _binary_gfx_anim_3_ppm_size; |
extern char _binary_gfx_anim_4_ppm_start[0]; |
extern int _binary_gfx_anim_4_ppm_size; |
static void make_anim(void) |
{ |
int an; |
int pm; |
an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]); |
int an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]); |
if (an < 0) |
return; |
pm = make_pixmap(_binary_anim_1_ppm_start, |
(int) &_binary_anim_1_ppm_size); |
int pm = make_pixmap(_binary_gfx_anim_1_ppm_start, |
(int) &_binary_gfx_anim_1_ppm_size); |
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm); |
pm = make_pixmap(_binary_anim_2_ppm_start, |
(int) &_binary_anim_2_ppm_size); |
pm = make_pixmap(_binary_gfx_anim_2_ppm_start, |
(int) &_binary_gfx_anim_2_ppm_size); |
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm); |
pm = make_pixmap(_binary_anim_3_ppm_start, |
(int) &_binary_anim_3_ppm_size); |
pm = make_pixmap(_binary_gfx_anim_3_ppm_start, |
(int) &_binary_gfx_anim_3_ppm_size); |
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm); |
pm = make_pixmap(_binary_anim_4_ppm_start, |
(int) &_binary_anim_4_ppm_size); |
pm = make_pixmap(_binary_gfx_anim_4_ppm_start, |
(int) &_binary_gfx_anim_4_ppm_size); |
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm); |
async_msg_1(fbphone, FB_ANIM_START, an); |
animation = an; |
} |
extern char _binary_cons_selected_ppm_start[0]; |
extern int _binary_cons_selected_ppm_size; |
extern char _binary_cons_idle_ppm_start[0]; |
extern int _binary_cons_idle_ppm_size; |
extern char _binary_cons_has_data_ppm_start[0]; |
extern int _binary_cons_has_data_ppm_size; |
extern char _binary_cons_kernel_ppm_start[0]; |
extern int _binary_cons_kernel_ppm_size; |
extern char _binary_gfx_cons_selected_ppm_start[0]; |
extern int _binary_gfx_cons_selected_ppm_size; |
extern char _binary_gfx_cons_idle_ppm_start[0]; |
extern int _binary_gfx_cons_idle_ppm_size; |
extern char _binary_gfx_cons_has_data_ppm_start[0]; |
extern int _binary_gfx_cons_has_data_ppm_size; |
extern char _binary_gfx_cons_kernel_ppm_start[0]; |
extern int _binary_gfx_cons_kernel_ppm_size; |
/** Initialize nice graphical console environment */ |
void gcons_init(int phone) |
{ |
int rc; |
int i; |
int status_start = STATUS_START; |
fbphone = phone; |
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres); |
int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres); |
if (rc) |
return; |
if (xres < 800 || yres < 600) |
if ((xres < 800) || (yres < 600)) |
return; |
/* create console viewport */ |
/* Create console viewport */ |
/* Align width & height to character size */ |
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP, |
ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8), |
ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16)); |
if (console_vp < 0) |
return; |
/* Create status buttons */ |
status_start += (xres - 800) / 2; |
size_t status_start = STATUS_START + (xres - 800) / 2; |
size_t i; |
for (i = 0; i < CONSOLE_COUNT; i++) { |
cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN + |
i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP, |
STATUS_WIDTH, STATUS_HEIGHT); |
if (cstatus_vp[i] < 0) |
return; |
vp_switch(cstatus_vp[i]); |
set_style(0x202020, 0xffffff); |
set_rgb_color(0x202020, 0xffffff); |
} |
/* Initialize icons */ |
ic_pixmaps[CONS_SELECTED] = |
make_pixmap(_binary_cons_selected_ppm_start, |
(int) &_binary_cons_selected_ppm_size); |
ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start, |
(int) &_binary_cons_idle_ppm_size); |
make_pixmap(_binary_gfx_cons_selected_ppm_start, |
(size_t) &_binary_gfx_cons_selected_ppm_size); |
ic_pixmaps[CONS_IDLE] = |
make_pixmap(_binary_gfx_cons_idle_ppm_start, |
(size_t) &_binary_gfx_cons_idle_ppm_size); |
ic_pixmaps[CONS_HAS_DATA] = |
make_pixmap(_binary_cons_has_data_ppm_start, |
(int) &_binary_cons_has_data_ppm_size); |
make_pixmap(_binary_gfx_cons_has_data_ppm_start, |
(size_t) &_binary_gfx_cons_has_data_ppm_size); |
ic_pixmaps[CONS_DISCONNECTED] = |
make_pixmap(_binary_cons_idle_ppm_start, |
(int) &_binary_cons_idle_ppm_size); |
ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start, |
(int) &_binary_cons_kernel_ppm_size); |
make_pixmap(_binary_gfx_cons_idle_ppm_start, |
(size_t) &_binary_gfx_cons_idle_ppm_size); |
ic_pixmaps[CONS_KERNEL] = |
make_pixmap(_binary_gfx_cons_kernel_ppm_start, |
(size_t) &_binary_gfx_cons_kernel_ppm_size); |
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED]; |
make_anim(); |
use_gcons = 1; |
use_gcons = true; |
console_state[0] = CONS_DISCONNECTED_SEL; |
console_state[KERNEL_CONSOLE] = CONS_KERNEL; |
gcons_redraw_console(); |
vp_switch(console_vp); |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/console/gcons.h |
---|
27,24 → 27,30 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
#ifndef _GCONS_H_ |
#define _GCONS_H_ |
#ifndef GCONS_H_ |
#define GCONS_H_ |
#include <sys/types.h> |
void gcons_init(int phone); |
void gcons_change_console(int consnum); |
void gcons_notify_char(int consnum); |
void gcons_redraw_console(void); |
void gcons_change_console(size_t index); |
void gcons_notify_char(size_t index); |
void gcons_in_kernel(void); |
void gcons_notify_connect(int consnum); |
void gcons_notify_disconnect(int consnum); |
void gcons_mouse_move(int dx, int dy); |
int gcons_mouse_btn(int state); |
void gcons_notify_connect(size_t index); |
void gcons_notify_disconnect(size_t index); |
void gcons_mouse_move(ssize_t dx, ssize_t dy); |
int gcons_mouse_btn(bool state); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/console/screenbuffer.c |
---|
27,48 → 27,55 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
#include <screenbuffer.h> |
#include <io/style.h> |
#include <malloc.h> |
#include <unistd.h> |
/** Store one character to screenbuffer. Its position is determined by |
* scr->position_x and scr->position_y. |
/** Store one character to screenbuffer. |
* |
* @param scr screenbuffer |
* @param c stored character |
* Its position is determined by scr->position_x |
* and scr->position_y. |
* |
* @param scr Screenbuffer |
* @param c Stored character |
* |
*/ |
void screenbuffer_putchar(screenbuffer_t *scr, char c) |
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t ch) |
{ |
keyfield_t *field; |
keyfield_t *field = |
get_field_at(scr, scr->position_x, scr->position_y); |
field = get_field_at(scr, scr->position_x, scr->position_y); |
field->character = c; |
field->style = scr->style; |
field->character = ch; |
field->attrs = scr->attrs; |
} |
/** Initilize screenbuffer. Allocate space for screen content in accordance to given size. |
* @param scr initialized screenbuffer |
* @param size_x width in characters |
* @param size_y height in characters |
* @return pointer to screenbuffer (same as scr parameter) or NULL |
/** Initilize screenbuffer. |
* |
* Allocate space for screen content in accordance to given size. |
* |
* @param scr Initialized screenbuffer |
* @param size_x Width in characters |
* @param size_y Height in characters |
* |
* @return Pointer to screenbuffer (same as scr parameter) or NULL |
* |
*/ |
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y) |
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y) |
{ |
scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y); |
if (!scr->buffer) { |
if (!scr->buffer) |
return NULL; |
} |
scr->size_x = size_x; |
scr->size_y = size_y; |
scr->style.fg_color = DEFAULT_FOREGROUND; |
scr->style.bg_color = DEFAULT_BACKGROUND; |
scr->attrs.t = at_style; |
scr->attrs.a.s.style = STYLE_NORMAL; |
scr->is_cursor_visible = 1; |
screenbuffer_clear(scr); |
76,56 → 83,63 |
return scr; |
} |
/** Clear screenbuffer. |
* @param scr screenbuffer |
/** Clear screenbuffer. |
* |
* @param scr Screenbuffer |
* |
*/ |
void screenbuffer_clear(screenbuffer_t *scr) |
{ |
unsigned int i; |
size_t i; |
for (i = 0; i < (scr->size_x * scr->size_y); i++) { |
scr->buffer[i].character = ' '; |
scr->buffer[i].style = scr->style; |
scr->buffer[i].attrs = scr->attrs; |
} |
scr->top_line = 0; |
scr->position_x = 0; |
scr->position_y = 0; |
scr->position_x = 0; |
} |
/** Clear one buffer line. |
* |
* @param scr |
* @param line One buffer line (not a screen line!) |
* |
*/ |
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line) |
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line) |
{ |
unsigned int i; |
size_t x; |
for (i = 0; i < scr->size_x; i++) { |
scr->buffer[i + line * scr->size_x].character = ' '; |
scr->buffer[i + line * scr->size_x].style = scr->style; |
for (x = 0; x < scr->size_x; x++) { |
scr->buffer[x + line * scr->size_x].character = ' '; |
scr->buffer[x + line * scr->size_x].attrs = scr->attrs; |
} |
} |
/** Copy content buffer from screenbuffer to given memory. |
* @param scr source screenbuffer |
* @param dest destination |
* |
* @param scr Source screenbuffer |
* @param dest Destination |
* |
*/ |
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest) |
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest) |
{ |
unsigned int i; |
size_t i; |
for (i = 0; i < scr->size_x * scr->size_y; i++) { |
for (i = 0; i < (scr->size_x * scr->size_y); i++) |
dest[i] = scr->buffer[i]; |
} |
} |
/** Set new cursor position in screenbuffer. |
* |
* @param scr |
* @param x |
* @param y |
* |
*/ |
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y) |
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y) |
{ |
scr->position_x = x % scr->size_x; |
scr->position_y = y % scr->size_y; |
132,16 → 146,46 |
} |
/** Set new style. |
* |
* @param scr |
* @param fg_color |
* @param bg_color |
* |
*/ |
void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color) |
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style) |
{ |
scr->style.fg_color = fg_color; |
scr->style.bg_color = bg_color; |
scr->attrs.t = at_style; |
scr->attrs.a.s.style = style; |
} |
/** Set new color. |
* |
* @param scr |
* @param fg_color |
* @param bg_color |
* |
*/ |
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags) |
{ |
scr->attrs.t = at_idx; |
scr->attrs.a.i.fg_color = fg_color; |
scr->attrs.a.i.bg_color = bg_color; |
scr->attrs.a.i.flags = flags; |
} |
/** Set new RGB color. |
* |
* @param scr |
* @param fg_color |
* @param bg_color |
* |
*/ |
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color) |
{ |
scr->attrs.t = at_rgb; |
scr->attrs.a.r.fg_color = fg_color; |
scr->attrs.a.r.bg_color = bg_color; |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/console/Makefile |
---|
31,8 → 31,9 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I. -I../kbd/include -I../fb |
LIBS = $(LIBC_PREFIX)/libc.a |
41,22 → 42,30 |
# |
OUTPUT = console |
GENERIC_SOURCES = \ |
console.c \ |
screenbuffer.c \ |
../kbd/generic/key_buffer.c \ |
../kbd/generic/keybuffer.c \ |
gcons.c |
IMAGES = helenos.ppm nameic.ppm cons_selected.ppm cons_idle.ppm \ |
cons_has_data.ppm cons_kernel.ppm anim_1.ppm anim_2.ppm anim_3.ppm \ |
anim_4.ppm |
IMAGES = \ |
gfx/helenos.ppm \ |
gfx/nameic.ppm \ |
gfx/cons_selected.ppm \ |
gfx/cons_idle.ppm \ |
gfx/cons_has_data.ppm \ |
gfx/cons_kernel.ppm \ |
gfx/anim_1.ppm \ |
gfx/anim_2.ppm \ |
gfx/anim_3.ppm \ |
gfx/anim_4.ppm |
ARCH_SOURCES = |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) \ |
$(addsuffix .o,$(basename $(IMAGES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
$(addsuffix .o,$(basename $(IMAGES))) |
OBJECTS := $(GENERIC_OBJECTS) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
64,18 → 73,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/console/gfx/anim_1.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/anim_2.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/anim_3.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/cons_has_data.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/anim_4.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/cons_selected.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/nameic.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/helenos.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/cons_idle.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/gfx/cons_kernel.ppm |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/arm/uspace/srv/console/console.h |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup console |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
35,20 → 35,10 |
#ifndef __CONSOLE_H__ |
#define __CONSOLE_H__ |
#define KERNEL_CONSOLE 11 |
#define CONSOLE_COUNT 12 |
#define KERNEL_CONSOLE 11 |
#define CONSOLE_COUNT 12 |
#endif |
#define CONSOLE_GETCHAR 1026 |
#define CONSOLE_PUTCHAR 1027 |
#define CONSOLE_CLEAR 1028 |
#define CONSOLE_GOTO 1029 |
#define CONSOLE_GETSIZE 1030 |
#define CONSOLE_FLUSH 1031 |
#define CONSOLE_SET_STYLE 1032 |
#define CONSOLE_CURSOR_VISIBILITY 1033 |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/fb/serial_console.c |
---|
0,0 → 1,462 |
/* |
* 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 <ipc/ipc.h> |
#include <async.h> |
#include <ipc/fb.h> |
#include <bool.h> |
#include <errno.h> |
#include <io/color.h> |
#include <io/style.h> |
#include <string.h> |
#include "../console/screenbuffer.h" |
#include "main.h" |
#include "serial_console.h" |
#define MAX_CONTROL 20 |
static void serial_sgr(const unsigned int mode); |
void serial_putchar(wchar_t ch); |
static int scr_width; |
static int scr_height; |
static bool color = true; /** True if producing color output. */ |
static bool utf8 = false; /** True if producing UTF8 output. */ |
static putc_function_t putc_function; |
/* Allow only 1 connection */ |
static int client_connected = 0; |
enum sgr_color_index { |
CI_BLACK = 0, |
CI_RED = 1, |
CI_GREEN = 2, |
CI_BROWN = 3, |
CI_BLUE = 4, |
CI_MAGENTA = 5, |
CI_CYAN = 6, |
CI_WHITE = 7, |
}; |
enum sgr_command { |
SGR_RESET = 0, |
SGR_BOLD = 1, |
SGR_BLINK = 5, |
SGR_REVERSE = 7, |
SGR_NORMAL_INT = 22, |
SGR_BLINK_OFF = 25, |
SGR_REVERSE_OFF = 27, |
SGR_FGCOLOR = 30, |
SGR_BGCOLOR = 40 |
}; |
static int color_map[] = { |
[COLOR_BLACK] = CI_BLACK, |
[COLOR_BLUE] = CI_RED, |
[COLOR_GREEN] = CI_GREEN, |
[COLOR_CYAN] = CI_CYAN, |
[COLOR_RED] = CI_RED, |
[COLOR_MAGENTA] = CI_MAGENTA, |
[COLOR_YELLOW] = CI_BROWN, |
[COLOR_WHITE] = CI_WHITE |
}; |
void serial_puts(char *str) |
{ |
while (*str) |
putc_function(*(str++)); |
} |
void serial_putchar(wchar_t ch) |
{ |
uint8_t buf[STR_BOUNDS(1)]; |
size_t offs; |
size_t i; |
if (utf8 != true) { |
if (ch >= 0 && ch < 128) |
(*putc_function)((uint8_t) ch); |
else |
(*putc_function)('?'); |
return; |
} |
offs = 0; |
if (chr_encode(ch, buf, &offs, STR_BOUNDS(1)) == EOK) { |
for (i = 0; i < offs; i++) |
(*putc_function)(buf[i]); |
} else { |
(*putc_function)('?'); |
} |
} |
void serial_goto(const unsigned int col, const unsigned int row) |
{ |
if ((col > scr_width) || (row > scr_height)) |
return; |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1); |
serial_puts(control); |
} |
void serial_clrscr(void) |
{ |
/* Initialize graphic rendition attributes. */ |
serial_sgr(SGR_RESET); |
if (color) { |
serial_sgr(SGR_FGCOLOR + CI_BLACK); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_puts("\033[2J"); |
} |
void serial_scroll(int i) |
{ |
if (i > 0) { |
serial_goto(0, scr_height - 1); |
while (i--) |
serial_puts("\033D"); |
} else if (i < 0) { |
serial_goto(0, 0); |
while (i++) |
serial_puts("\033M"); |
} |
} |
/** ECMA-48 Set Graphics Rendition. */ |
static void serial_sgr(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
serial_puts(control); |
} |
/** Set scrolling region. */ |
void serial_set_scroll_region(unsigned last_row) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[0;%ur", last_row); |
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) |
{ |
scr_width = w; |
scr_height = h; |
putc_function = putc_fn; |
} |
static void serial_set_style(int style) |
{ |
if (style == STYLE_EMPHASIS) { |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + CI_RED); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_sgr(SGR_BOLD); |
} else { |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + CI_BLACK); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_sgr(SGR_NORMAL_INT); |
} |
} |
static void serial_set_idx(unsigned fgcolor, unsigned bgcolor, |
unsigned flags) |
{ |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + color_map[fgcolor]); |
serial_sgr(SGR_BGCOLOR + color_map[bgcolor]); |
} else { |
if (fgcolor < bgcolor) |
serial_sgr(SGR_RESET); |
else |
serial_sgr(SGR_REVERSE); |
} |
} |
static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor) |
{ |
if (fgcolor < bgcolor) |
serial_sgr(SGR_REVERSE_OFF); |
else |
serial_sgr(SGR_REVERSE); |
} |
static void serial_set_attrs(const attrs_t *a) |
{ |
switch (a->t) { |
case at_style: |
serial_set_style(a->a.s.style); |
break; |
case at_rgb: |
serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); |
break; |
case at_idx: |
serial_set_idx(a->a.i.fg_color, |
a->a.i.bg_color, a->a.i.flags); |
break; |
default: |
break; |
} |
} |
/** Draw text data to viewport. |
* |
* @param vport Viewport id |
* @param data Text data. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
*/ |
static void draw_text_data(keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
unsigned int i, j; |
keyfield_t *field; |
attrs_t *a0, *a1; |
serial_goto(x, y); |
a0 = &data[0].attrs; |
serial_set_attrs(a0); |
for (j = 0; j < h; j++) { |
if (j > 0 && w != scr_width) |
serial_goto(x, j); |
for (i = 0; i < w; i++) { |
field = &data[j * w + i]; |
a1 = &field->attrs; |
if (!attrs_same(*a0, *a1)) |
serial_set_attrs(a1); |
serial_putchar(field->character); |
a0 = a1; |
} |
} |
} |
int lastcol = 0; |
int lastrow = 0; |
/** |
* Main function of the thread serving client connections. |
*/ |
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
keyfield_t *interbuf = NULL; |
size_t intersize = 0; |
wchar_t c; |
int col, row, w, h; |
int i; |
attrs_t cur_attr; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
cur_attr.t = at_style; |
cur_attr.a.s.style = STYLE_NORMAL; |
/* Clear the terminal, set scrolling region |
to 0 - height rows. */ |
serial_clrscr(); |
serial_goto(0, 0); |
serial_set_scroll_region(scr_height); |
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 IPC_M_SHARE_OUT: |
/* We accept one area for data interchange */ |
intersize = IPC_GET_ARG2(call); |
if (intersize >= scr_width * scr_height * |
sizeof(*interbuf)) { |
receive_comm_area(callid, &call, |
(void *) &interbuf); |
continue; |
} |
retval = EINVAL; |
break; |
case FB_DRAW_TEXT_DATA: |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
w = IPC_GET_ARG3(call); |
h = IPC_GET_ARG4(call); |
if (!interbuf) { |
retval = EINVAL; |
break; |
} |
if (col + w > scr_width || row + h > scr_height) { |
retval = EINVAL; |
break; |
} |
draw_text_data(interbuf, col, row, w, h); |
lastcol = col + w; |
lastrow = row + h - 1; |
retval = 0; |
break; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
row = IPC_GET_ARG3(call); |
if ((lastcol != col) || (lastrow != row)) |
serial_goto(col, row); |
lastcol = col + 1; |
lastrow = row; |
serial_putchar(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
serial_goto(col, row); |
lastcol = col; |
lastrow = row; |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED : |
FB_CCAP_STYLE); |
continue; |
case FB_CLEAR: |
serial_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
cur_attr.t = at_style; |
cur_attr.a.s.style = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
case FB_SET_COLOR: |
cur_attr.t = at_idx; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
cur_attr.a.i.flags = IPC_GET_ARG3(call); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
cur_attr.t = at_rgb; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > scr_height) || (i < -scr_height)) { |
retval = EINVAL; |
break; |
} |
serial_scroll(i); |
serial_goto(lastcol, lastrow); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
serial_cursor_enable(); |
else |
serial_cursor_disable(); |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
serial_sgr(SGR_RESET); |
serial_puts("\033[2J"); |
serial_goto(0, 0); |
serial_cursor_enable(); |
retval = 0; |
break; |
case FB_SCREEN_RECLAIM: |
serial_clrscr(); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fb/fb.c |
---|
1,4 → 1,5 |
/* |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2006 Jakub Vana |
* Copyright (c) 2006 Ondrej Palkovsky |
* All rights reserved. |
29,10 → 30,10 |
/** |
* @defgroup fb Graphical framebuffer |
* @brief HelenOS graphical framebuffer. |
* @brief HelenOS graphical framebuffer. |
* @ingroup fbs |
* @{ |
*/ |
*/ |
/** @file |
*/ |
50,8 → 51,12 |
#include <ipc/services.h> |
#include <kernel/errno.h> |
#include <kernel/genarch/fb/visuals.h> |
#include <io/color.h> |
#include <io/style.h> |
#include <async.h> |
#include <fibril.h> |
#include <bool.h> |
#include <stdio.h> |
#include "font-8x16.h" |
#include "fb.h" |
62,594 → 67,849 |
#include "pointer.xbm" |
#include "pointer_mask.xbm" |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x0 |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x000000 |
/***************************************************************/ |
/* Pixel specific fuctions */ |
#define GLYPH_UNAVAIL '?' |
typedef void (*conv2scr_fn_t)(void *, int); |
typedef int (*conv2rgb_fn_t)(void *); |
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
#define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
#define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
/** Function to render a bit mask. */ |
typedef void (*mask_conv_t)(void *, bool); |
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
struct { |
uint8_t *fbaddress; |
uint8_t *fb_addr; |
unsigned int xres; |
unsigned int yres; |
unsigned int scanline; |
unsigned int glyphscanline; |
unsigned int pixelbytes; |
unsigned int invert_colors; |
conv2scr_fn_t rgb2scr; |
conv2rgb_fn_t scr2rgb; |
unsigned int glyphbytes; |
/** Pre-rendered mask for rendering glyphs. Specific for the visual. */ |
uint8_t *glyphs; |
rgb_conv_t rgb_conv; |
mask_conv_t mask_conv; |
} screen; |
/** Backbuffer character cell. */ |
typedef struct { |
int initialized; |
unsigned int x, y; |
unsigned int width, height; |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
} bb_cell_t; |
typedef struct { |
bool initialized; |
unsigned int x; |
unsigned int y; |
unsigned int width; |
unsigned int height; |
/* Text support in window */ |
unsigned int rows, cols; |
/* Style for text printing */ |
style_t style; |
unsigned int cols; |
unsigned int rows; |
/* |
* Style and glyphs for text printing |
*/ |
/** Current attributes. */ |
attr_rgb_t attr; |
uint8_t *bgpixel; |
/** |
* Glyph drawing function for this viewport. Different viewports |
* might use different drawing functions depending on whether their |
* scanlines are aligned on a word boundary. |
*/ |
dg_t dglyph; |
/* Auto-cursor position */ |
int cursor_active, cur_col, cur_row; |
int cursor_shown; |
/* Double buffering */ |
uint8_t *dbdata; |
unsigned int dboffset; |
unsigned int paused; |
bool cursor_active; |
unsigned int cur_col; |
unsigned int cur_row; |
bool cursor_shown; |
/* Back buffer */ |
bb_cell_t *backbuf; |
unsigned int bbsize; |
} viewport_t; |
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
typedef struct { |
int initialized; |
int enabled; |
bool initialized; |
bool enabled; |
unsigned int vp; |
unsigned int pos; |
unsigned int animlen; |
unsigned int pixmaps[MAX_ANIM_LEN]; |
} animation_t; |
static animation_t animations[MAX_ANIMATIONS]; |
static int anims_enabled; |
static bool anims_enabled; |
/** Maximum number of saved pixmaps |
* Pixmap is a saved rectangle |
*/ |
#define MAX_PIXMAPS 256 |
typedef struct { |
unsigned int width; |
unsigned int height; |
uint8_t *data; |
} pixmap_t; |
static pixmap_t pixmaps[MAX_PIXMAPS]; |
/* Viewport is a rectangular area on the screen */ |
#define MAX_VIEWPORTS 128 |
static viewport_t viewports[128]; |
/* Allow only 1 connection */ |
static int client_connected = 0; |
static bool client_connected = false; /**< Allow only 1 connection */ |
#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
static uint32_t color_table[16] = { |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
}; |
#define COL_WIDTH 8 |
#define ROW_BYTES (screen.scanline * FONT_SCANLINES) |
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a); |
static int rgb_from_style(attr_rgb_t *rgb, int style); |
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags); |
#define POINTPOS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes) |
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t attr); |
static inline int COLOR(int color) |
{ |
return screen.invert_colors ? ~color : color; |
} |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
/* Conversion routines between different color representations */ |
static void |
rgb_byte0888(void *dst, int rgb) |
{ |
*(int *)dst = rgb; |
} |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row); |
static int |
byte0888_rgb(void *src) |
{ |
return (*(int *)src) & 0xffffff; |
} |
static void |
bgr_byte0888(void *dst, int rgb) |
{ |
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 | |
RED(rgb, 8); |
} |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
static int |
byte0888_bgr(void *src) |
{ |
int color = *(uint32_t *)(src); |
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) | |
((color >> 16) & 0xff); |
} |
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
static void bgr_byte8880(void *dst, int rgb) |
{ |
uint8_t *scr = (uint8_t *) dst; |
scr[3] = RED(rgb, 8); |
scr[2] = GREEN(rgb, 8); |
scr[1] = BLUE(rgb, 8); |
} |
#define X2COL(x) ((x) / FONT_WIDTH) |
#define Y2ROW(y) ((y) / FONT_SCANLINES) |
static int byte8880_bgr(void *src) |
{ |
uint8_t *scr = (uint8_t *) src; |
return scr[3] << 16 | scr[2] << 8 | scr[1]; |
} |
#define FB_POS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes) |
#define BB_POS(vport, col, row) ((row) * vport->cols + (col)) |
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline) |
static void |
rgb_byte888(void *dst, int rgb) |
/** ARGB 8:8:8:8 conversion |
* |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
uint8_t *scr = dst; |
#if defined(FB_INVERT_ENDIAN) |
scr[0] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[2] = BLUE(rgb, 8); |
#else |
scr[2] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[0] = BLUE(rgb, 8); |
#endif |
*((uint32_t *) dst) = rgb & 0x00ffffff; |
} |
static int |
byte888_rgb(void *src) |
static void mask_0888(void *dst, bool mask) |
{ |
uint8_t *scr = src; |
#if defined(FB_INVERT_ENDIAN) |
return scr[0] << 16 | scr[1] << 8 | scr[2]; |
#else |
return scr[2] << 16 | scr[1] << 8 | scr[0]; |
#endif |
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0); |
} |
/** 16-bit depth (5:5:5) */ |
static void |
rgb_byte555(void *dst, int rgb) |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
/* 5-bit, 5-bits, 5-bits */ |
*((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 | |
BLUE(rgb, 5); |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
} |
/** 16-bit depth (5:5:5) */ |
static int |
byte555_rgb(void *src) |
/** RGB 8:8:8 conversion |
* |
*/ |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 10) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3); |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
/** 16-bit depth (5:6:5) */ |
static void |
rgb_byte565(void *dst, int rgb) |
static void mask_888(void *dst, bool mask) |
{ |
/* 5-bit, 6-bits, 5-bits */ |
*((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | |
BLUE(rgb, 5); |
if (mask) { |
((uint8_t *) dst)[0] = 0xff; |
((uint8_t *) dst)[1] = 0xff; |
((uint8_t *) dst)[2] = 0xff; |
} else { |
((uint8_t *) dst)[0] = 0; |
((uint8_t *) dst)[1] = 0; |
((uint8_t *) dst)[2] = 0; |
} |
} |
/** 16-bit depth (5:6:5) */ |
static int |
byte565_rgb(void *src) |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 11) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3); |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
/** Put pixel - 8-bit depth (3:2:3) */ |
static void |
rgb_byte8(void *dst, int rgb) |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
{ |
*(uint8_t *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
/** Return pixel color - 8-bit depth (3:2:3) */ |
static int |
byte8_rgb(void *src) |
static void mask_555(void *dst, bool mask) |
{ |
int color = *(uint8_t *)src; |
return (((color >> 5) & 0x7) << (16 + 5)) | |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5); |
*((uint16_t *) dst) = (mask ? 0x7fff : 0); |
} |
/** Put pixel into viewport |
/** RGB 5:6:5 conversion |
* |
* @param vport Viewport identification |
* @param x X coord relative to viewport |
* @param y Y coord relative to viewport |
* @param color RGB color |
*/ |
static void |
putpixel(viewport_t *vport, unsigned int x, unsigned int y, int color) |
static void rgb_565(void *dst, uint32_t rgb) |
{ |
int dx = vport->x + x; |
int dy = vport->y + y; |
if (! (vport->paused && vport->dbdata)) |
(*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)], |
COLOR(color)); |
if (vport->dbdata) { |
int dline = (y + vport->dboffset) % vport->height; |
int doffset = screen.pixelbytes * (dline * vport->width + x); |
(*screen.rgb2scr)(&vport->dbdata[doffset], COLOR(color)); |
} |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
/** Get pixel from viewport */ |
static int |
getpixel(viewport_t *vport, unsigned int x, unsigned int y) |
static void mask_565(void *dst, bool mask) |
{ |
int dx = vport->x + x; |
int dy = vport->y + y; |
return COLOR((*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx, dy)])); |
*((uint16_t *) dst) = (mask ? 0xffff : 0); |
} |
static inline void |
putpixel_mem(char *mem, unsigned int x, unsigned int y, int color) |
{ |
(*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color)); |
} |
static void |
draw_rectangle(viewport_t *vport, unsigned int sx, unsigned int sy, |
unsigned int width, unsigned int height, int color) |
/** RGB 3:2:3 |
* |
*/ |
static void rgb_323(void *dst, uint32_t rgb) |
{ |
unsigned int x, y; |
static void *tmpline; |
if (!tmpline) |
tmpline = malloc(screen.scanline * screen.pixelbytes); |
/* Clear first line */ |
for (x = 0; x < width; x++) |
putpixel_mem(tmpline, x, 0, color); |
if (!vport->paused) { |
/* Recompute to screen coords */ |
sx += vport->x; |
sy += vport->y; |
/* Copy the rest */ |
for (y = sy;y < sy+height; y++) |
memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline, |
screen.pixelbytes * width); |
} |
if (vport->dbdata) { |
for (y = sy; y < sy + height; y++) { |
int rline = (y + vport->dboffset) % vport->height; |
int rpos = (rline * vport->width + sx) * |
screen.pixelbytes; |
memcpy(&vport->dbdata[rpos], tmpline, |
screen.pixelbytes * width); |
} |
} |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
/** Fill viewport with background color */ |
static void |
clear_port(viewport_t *vport) |
static void mask_323(void *dst, bool mask) |
{ |
draw_rectangle(vport, 0, 0, vport->width, vport->height, |
vport->style.bg_color); |
*((uint8_t *) dst) = (mask ? 0xff : 0); |
} |
/** Scroll unbuffered viewport up/down |
/** Draw a filled rectangle. |
* |
* @param vport Viewport to scroll |
* @param lines Positive number - scroll up, negative - scroll down |
* @note Need real implementation that does not access VRAM twice. |
* |
*/ |
static void |
scroll_port_nodb(viewport_t *vport, int lines) |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
int y; |
if (lines > 0) { |
for (y = vport->y; y < vport->y+vport->height - lines; y++) |
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], |
&screen.fbaddress[POINTPOS(vport->x,y + lines)], |
screen.pixelbytes * vport->width); |
draw_rectangle(vport, 0, vport->height - lines, vport->width, |
lines, vport->style.bg_color); |
} else if (lines < 0) { |
lines = -lines; |
for (y = vport->y + vport->height-1; y >= vport->y + lines; y--) |
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], |
&screen.fbaddress[POINTPOS(vport->x,y - lines)], |
screen.pixelbytes * vport->width); |
draw_rectangle(vport, 0, 0, vport->width, lines, |
vport->style.bg_color); |
unsigned int x; |
unsigned int y; |
unsigned int copy_bytes; |
uint8_t *sp; |
uint8_t *dp; |
uint8_t cbuf[4]; |
if ((y0 >= y1) || (x0 >= x1)) |
return; |
screen.rgb_conv(cbuf, color); |
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
dp = sp; |
/* Draw the first line. */ |
for (x = x0; x < x1; x++) { |
memcpy(dp, cbuf, screen.pixelbytes); |
dp += screen.pixelbytes; |
} |
} |
/** Refresh given viewport from double buffer */ |
static void |
refresh_viewport_db(viewport_t *vport) |
{ |
unsigned int y, srcy, srcoff, dsty, dstx; |
for (y = 0; y < vport->height; y++) { |
srcy = (y + vport->dboffset) % vport->height; |
srcoff = (vport->width * srcy) * screen.pixelbytes; |
dstx = vport->x; |
dsty = vport->y + y; |
memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)], |
&vport->dbdata[srcoff], vport->width * screen.pixelbytes); |
dp = sp + screen.scanline; |
copy_bytes = (x1 - x0) * screen.pixelbytes; |
/* Draw the remaining lines by copying. */ |
for (y = y0 + 1; y < y1; y++) { |
memcpy(dp, sp, copy_bytes); |
dp += screen.scanline; |
} |
} |
/** Scroll viewport that has double buffering enabled */ |
static void |
scroll_port_db(viewport_t *vport, int lines) |
/** Redraw viewport. |
* |
* @param vport Viewport to redraw |
* |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
++vport->paused; |
if (lines > 0) { |
draw_rectangle(vport, 0, 0, vport->width, lines, |
vport->style.bg_color); |
vport->dboffset += lines; |
vport->dboffset %= vport->height; |
} else if (lines < 0) { |
lines = -lines; |
draw_rectangle(vport, 0, vport->height-lines, vport->width, |
lines, vport->style.bg_color); |
if (vport->dboffset < lines) |
vport->dboffset += vport->height; |
vport->dboffset -= lines; |
unsigned int col; |
unsigned int row; |
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
draw_vp_glyph(vport, false, col, row); |
} |
} |
--vport->paused; |
if (COL2X(vport->cols) < vport->width) { |
draw_filled_rect( |
vport->x + COL2X(vport->cols), vport->y, |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
refresh_viewport_db(vport); |
if (ROW2Y(vport->rows) < vport->height) { |
draw_filled_rect( |
vport->x, vport->y + ROW2Y(vport->rows), |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
} |
/** Scrolls viewport given number of lines */ |
static void |
scroll_port(viewport_t *vport, int lines) |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
if (vport->dbdata) |
scroll_port_db(vport, lines); |
else |
scroll_port_nodb(vport, lines); |
size_t i; |
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
backbuf[i].fg_color = fg_color; |
backbuf[i].bg_color = bg_color; |
} |
} |
static void |
invert_pixel(viewport_t *vport, unsigned int x, unsigned int y) |
/** Clear viewport. |
* |
* @param vport Viewport to clear |
* |
*/ |
static void vport_clear(viewport_t *vport) |
{ |
putpixel(vport, x, y, ~getpixel(vport, x, y)); |
backbuf_clear(vport->backbuf, vport->cols * vport->rows, |
vport->attr.fg_color, vport->attr.bg_color); |
vport_redraw(vport); |
} |
/***************************************************************/ |
/* Character-console functions */ |
/** Draw character at given position |
/** Scroll viewport by the specified number of lines. |
* |
* @param vport Viewport where the character is printed |
* @param sx Coordinates of top-left of the character |
* @param sy Coordinates of top-left of the character |
* @param style Color of the character |
* @param transparent If false, print background color |
* @param vport Viewport to scroll |
* @param lines Number of lines to scroll |
* |
*/ |
static void |
draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy, |
style_t style, int transparent) |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
int i; |
unsigned int col; |
unsigned int row; |
unsigned int x; |
unsigned int y; |
unsigned int glline; |
for (y = 0; y < FONT_SCANLINES; y++) { |
glline = fb_font[glyph * FONT_SCANLINES + y]; |
for (i = 0; i < 8; i++) { |
if (glline & (1 << (7 - i))) |
putpixel(vport, sx + i, sy + y, style.fg_color); |
else if (!transparent) |
putpixel(vport, sx + i, sy + y, style.bg_color); |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp; |
bb_cell_t *xbp; |
/* |
* Redraw. |
*/ |
y = vport->y; |
for (row = 0; row < vport->rows; row++) { |
x = vport->x; |
for (col = 0; col < vport->cols; col++) { |
if (((int) row + lines >= 0) && |
((int) row + lines < (int) vport->rows)) { |
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
glyph = xbp->glyph; |
fg_color = xbp->fg_color; |
bg_color = xbp->bg_color; |
if ((bbp->glyph == glyph) |
&& (bbp->fg_color == xbp->fg_color) |
&& (bbp->bg_color == xbp->bg_color)) { |
x += FONT_WIDTH; |
continue; |
} |
} else { |
glyph = 0; |
fg_color = vport->attr.fg_color; |
bg_color = vport->attr.bg_color; |
} |
(*vport->dglyph)(x, y, false, screen.glyphs, glyph, |
fg_color, bg_color); |
x += FONT_WIDTH; |
} |
y += FONT_SCANLINES; |
} |
/* |
* Scroll backbuffer. |
*/ |
if (lines > 0) { |
memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
vport->cols * (vport->rows - lines) * sizeof(bb_cell_t)); |
backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], |
vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color); |
} else { |
memmove(vport->backbuf - vport->cols * lines, vport->backbuf, |
vport->cols * (vport->rows + lines) * sizeof(bb_cell_t)); |
backbuf_clear(vport->backbuf, - vport->cols * lines, |
vport->attr.fg_color, vport->attr.bg_color); |
} |
} |
/** Invert character at given position */ |
static void |
invert_char(viewport_t *vport,unsigned int row, unsigned int col) |
/** Render glyphs |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
*/ |
static void render_glyphs(void) |
{ |
unsigned int x; |
unsigned int y; |
for (x = 0; x < COL_WIDTH; x++) |
for (y = 0; y < FONT_SCANLINES; y++) |
invert_pixel(vport, col * COL_WIDTH + x, row * |
FONT_SCANLINES + y); |
unsigned int glyph; |
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) { |
unsigned int y; |
for (y = 0; y < FONT_SCANLINES; y++) { |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) { |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? true : false); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? false : true); |
} |
} |
} |
} |
/***************************************************************/ |
/* Stdout specific functions */ |
/** Create new viewport |
* |
* @return New viewport number |
* @param x Origin of the viewport (x). |
* @param y Origin of the viewport (y). |
* @param width Width of the viewport. |
* @param height Height of the viewport. |
* |
* @return New viewport number. |
* |
*/ |
static int |
viewport_create(unsigned int x, unsigned int y,unsigned int width, |
unsigned int height) |
static int vport_create(unsigned int x, unsigned int y, |
unsigned int width, unsigned int height) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < MAX_VIEWPORTS; i++) { |
if (!viewports[i].initialized) |
break; |
} |
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
unsigned int cols = width / FONT_WIDTH; |
unsigned int rows = height / FONT_SCANLINES; |
unsigned int bbsize = cols * rows * sizeof(bb_cell_t); |
unsigned int word_size = sizeof(unsigned long); |
bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize); |
if (!backbuf) |
return ENOMEM; |
uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes); |
if (!bgpixel) { |
free(backbuf); |
return ENOMEM; |
} |
backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR); |
memset(bgpixel, 0, screen.pixelbytes); |
viewports[i].x = x; |
viewports[i].y = y; |
viewports[i].width = width; |
viewports[i].height = height; |
viewports[i].rows = height / FONT_SCANLINES; |
viewports[i].cols = width / COL_WIDTH; |
viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
viewports[i].cols = cols; |
viewports[i].rows = rows; |
viewports[i].attr.bg_color = DEFAULT_BGCOLOR; |
viewports[i].attr.fg_color = DEFAULT_FGCOLOR; |
viewports[i].bgpixel = bgpixel; |
/* |
* Conditions necessary to select aligned version: |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
*/ |
if (((word_size % screen.pixelbytes) == 0) |
&& ((FONT_WIDTH * screen.pixelbytes) % word_size == 0) |
&& ((x * screen.pixelbytes) % word_size == 0) |
&& (screen.scanline % word_size == 0)) { |
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
} |
viewports[i].cur_col = 0; |
viewports[i].cur_row = 0; |
viewports[i].cursor_active = 0; |
viewports[i].initialized = 1; |
viewports[i].cursor_active = false; |
viewports[i].cursor_shown = false; |
viewports[i].bbsize = bbsize; |
viewports[i].backbuf = backbuf; |
viewports[i].initialized = true; |
screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color); |
return i; |
} |
/** Initialize framebuffer as a chardev output device |
* |
* @param addr Address of theframebuffer |
* @param xres Screen width in pixels |
* @param yres Screen height in pixels |
* @param visual Bits per pixel (8, 16, 24, 32) |
* @param scan Bytes per one scanline |
* @param invert_colors Inverted colors. |
* @param addr Address of the framebuffer |
* @param xres Screen width in pixels |
* @param yres Screen height in pixels |
* @param visual Bits per pixel (8, 16, 24, 32) |
* @param scan Bytes per one scanline |
* |
*/ |
static bool |
screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual, bool invert_colors) |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb2scr = rgb_byte8; |
screen.scr2rgb = byte8_rgb; |
screen.rgb_conv = rgb_323; |
screen.mask_conv = mask_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb2scr = rgb_byte555; |
screen.scr2rgb = byte555_rgb; |
screen.rgb_conv = rgb_555; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb2scr = rgb_byte565; |
screen.scr2rgb = byte565_rgb; |
screen.rgb_conv = rgb_565; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb2scr = rgb_byte888; |
screen.scr2rgb = byte888_rgb; |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
screen.rgb_conv = bgr_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb2scr = rgb_byte888; |
screen.scr2rgb = byte888_rgb; |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
screen.rgb2scr = rgb_byte0888; |
screen.scr2rgb = byte0888_rgb; |
screen.rgb_conv = rgb_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
screen.rgb2scr = bgr_byte0888; |
screen.scr2rgb = byte0888_bgr; |
screen.rgb_conv = bgr_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_8_8_8_0: |
screen.rgb2scr = bgr_byte8880; |
screen.scr2rgb = byte8880_bgr; |
screen.pixelbytes = 4; |
break; |
default: |
return false; |
} |
screen.fbaddress = (unsigned char *) addr; |
screen.fb_addr = (unsigned char *) addr; |
screen.xres = xres; |
screen.yres = yres; |
screen.scanline = scan; |
screen.invert_colors = invert_colors; |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) |
return false; |
memset(glyphs, 0, glyphsize); |
screen.glyphs = glyphs; |
render_glyphs(); |
/* Create first viewport */ |
viewport_create(0, 0, xres, yres); |
vport_create(0, 0, xres, yres); |
return true; |
} |
/** Hide cursor if it is shown */ |
static void |
cursor_hide(viewport_t *vport) |
/** Draw a glyph, takes advantage of alignment. |
* |
* This version can only be used if the following conditions are met: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
* It makes use of the pre-rendered mask to process (possibly) several |
* pixels at once (word size / pixelbytes pixels at a time are processed) |
* making it very fast. Most notably this version is not applicable at 24 bits |
* per pixel. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
if (vport->cursor_active && vport->cursor_shown) { |
invert_char(vport, vport->cur_row, vport->cur_col); |
vport->cursor_shown = 0; |
unsigned int i; |
unsigned int yd; |
unsigned long fg_buf; |
unsigned long bg_buf; |
unsigned long mask; |
/* |
* Prepare a pair of words, one filled with foreground-color |
* pattern and the other filled with background-color pattern. |
*/ |
for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes], |
fg_color); |
screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes], |
bg_color); |
} |
/* Pointer to the current position in the mask. */ |
unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
/* Pointer to the current position on the screen. */ |
unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
/* Width of the character cell in words. */ |
unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
/* Offset to add when moving to another screen scanline. */ |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
* Now process the cell scanline, combining foreground |
* and background color patters using the pre-rendered mask. |
*/ |
for (i = 0; i < ww; i++) { |
mask = *maskp++; |
*dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp = (unsigned long *) ((uint8_t *) dp + d_add); |
} |
} |
/** Show cursor if cursor showing is enabled */ |
static void |
cursor_print(viewport_t *vport) |
/** Draw a glyph, fallback version. |
* |
* This version does not make use of the pre-rendered mask, it uses |
* the font bitmap directly. It works always, but it is slower. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i; |
unsigned int j; |
unsigned int yd; |
uint8_t fg_buf[4]; |
uint8_t bg_buf[4]; |
uint8_t *sp; |
uint8_t b; |
/* Pre-render 1x the foreground and background color pixels. */ |
if (cursor) { |
screen.rgb_conv(fg_buf, bg_color); |
screen.rgb_conv(bg_buf, fg_color); |
} else { |
screen.rgb_conv(fg_buf, fg_color); |
screen.rgb_conv(bg_buf, bg_color); |
} |
/* Pointer to the current position on the screen. */ |
uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
/* Offset to add when moving to another screen scanline. */ |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
b = fb_font[glyph][yd]; |
for (i = 0; i < FONT_WIDTH; i++) { |
/* Choose color based on the current bit. */ |
sp = (b & 0x80) ? fg_buf : bg_buf; |
/* Copy the pixel. */ |
for (j = 0; j < screen.pixelbytes; j++) { |
*dp++ = *sp++; |
} |
/* Move to the next bit. */ |
b = b << 1; |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp += d_add; |
} |
} |
/** Draw glyph at specified position in viewport. |
* |
* @param vport Viewport identification |
* @param cursor Draw glyph with cursor |
* @param col Screen position relative to viewport |
* @param row Screen position relative to viewport |
* |
*/ |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row) |
{ |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
(*vport->dglyph)(x, y, cursor, screen.glyphs, glyph, |
fg_color, bg_color); |
} |
/** Hide cursor if it is shown |
* |
*/ |
static void cursor_hide(viewport_t *vport) |
{ |
if ((vport->cursor_active) && (vport->cursor_shown)) { |
draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row); |
vport->cursor_shown = false; |
} |
} |
/** Show cursor if cursor showing is enabled |
* |
*/ |
static void cursor_show(viewport_t *vport) |
{ |
/* Do not check for cursor_shown */ |
if (vport->cursor_active) { |
invert_char(vport, vport->cur_row, vport->cur_col); |
vport->cursor_shown = 1; |
draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row); |
vport->cursor_shown = true; |
} |
} |
/** Invert cursor, if it is enabled */ |
static void |
cursor_blink(viewport_t *vport) |
/** Invert cursor, if it is enabled |
* |
*/ |
static void cursor_blink(viewport_t *vport) |
{ |
if (vport->cursor_shown) |
cursor_hide(vport); |
else |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Draw character at given position relative to viewport |
* |
* @param vport Viewport identification |
* @param c Character to print |
* @param row Screen position relative to viewport |
* @param col Screen position relative to viewport |
* @param transparent If false, print background color with character |
/** Draw character at given position relative to viewport |
* |
* @param vport Viewport identification |
* @param c Character to draw |
* @param col Screen position relative to viewport |
* @param row Screen position relative to viewport |
* |
*/ |
static void |
draw_char(viewport_t *vport, char c, unsigned int row, unsigned int col, |
style_t style, int transparent) |
static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row) |
{ |
/* Optimize - do not hide cursor if we are going to overwrite it */ |
if (vport->cursor_active && vport->cursor_shown && |
(vport->cur_col != col || vport->cur_row != row)) |
invert_char(vport, vport->cur_row, vport->cur_col); |
bb_cell_t *bbp; |
draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style, |
transparent); |
/* Do not hide cursor if we are going to overwrite it */ |
if ((vport->cursor_active) && (vport->cursor_shown) && |
((vport->cur_col != col) || (vport->cur_row != row))) |
cursor_hide(vport); |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
bbp->glyph = fb_font_glyph(c); |
bbp->fg_color = vport->attr.fg_color; |
bbp->bg_color = vport->attr.bg_color; |
draw_vp_glyph(vport, false, col, row); |
vport->cur_col = col; |
vport->cur_row = row; |
vport->cur_col++; |
if (vport->cur_col >= vport->cols) { |
vport->cur_col = 0; |
657,65 → 917,97 |
if (vport->cur_row >= vport->rows) |
vport->cur_row--; |
} |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Draw text data to viewport |
/** Draw text data to viewport. |
* |
* @param vport Viewport id |
* @param data Text data fitting exactly into viewport |
* @param data Text data. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* |
*/ |
static void |
draw_text_data(viewport_t *vport, keyfield_t *data) |
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
int i; |
int col,row; |
clear_port(vport); |
for (i = 0; i < vport->cols * vport->rows; i++) { |
if (data[i].character == ' ' && style_same(data[i].style, |
vport->style)) |
continue; |
col = i % vport->cols; |
row = i / vport->cols; |
draw_glyph(vport, data[i].character, col * COL_WIDTH, row * |
FONT_SCANLINES, data[i].style, style_same(data[i].style, |
vport->style)); |
unsigned int i; |
unsigned int j; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |
for (j = 0; j < h; j++) { |
for (i = 0; i < w; i++) { |
unsigned int col = x + i; |
unsigned int row = y + j; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
a = &data[j * w + i].attrs; |
rgb_from_attr(&rgb, a); |
bbp->glyph = fb_font_glyph(data[j * w + i].character); |
bbp->fg_color = rgb.fg_color; |
bbp->bg_color = rgb.bg_color; |
draw_vp_glyph(vport, false, col, row); |
} |
} |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Return first free pixmap */ |
static int |
find_free_pixmap(void) |
static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color) |
{ |
int i; |
int pm = *((int *) data); |
pixmap_t *pmap = &pixmaps[pm]; |
unsigned int pos = (y * pmap->width + x) * screen.pixelbytes; |
for (i = 0;i < MAX_PIXMAPS;i++) |
screen.rgb_conv(&pmap->data[pos], color); |
} |
static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color) |
{ |
viewport_t *vport = (viewport_t *) data; |
unsigned int dx = vport->x + x; |
unsigned int dy = vport->y + y; |
screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color); |
} |
/** Return first free pixmap |
* |
*/ |
static int find_free_pixmap(void) |
{ |
unsigned int i; |
for (i = 0; i < MAX_PIXMAPS; i++) |
if (!pixmaps[i].data) |
return i; |
return -1; |
} |
static void |
putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color) |
{ |
pixmap_t *pmap = &pixmaps[pm]; |
int pos = (y * pmap->width + x) * screen.pixelbytes; |
(*screen.rgb2scr)(&pmap->data[pos],COLOR(color)); |
} |
/** Create a new pixmap and return appropriate ID */ |
static int |
shm2pixmap(unsigned char *shm, size_t size) |
/** Create a new pixmap and return appropriate ID |
* |
*/ |
static int shm2pixmap(unsigned char *shm, size_t size) |
{ |
int pm; |
pixmap_t *pmap; |
pm = find_free_pixmap(); |
if (pm == -1) |
return ELIMIT; |
pmap = &pixmaps[pm]; |
if (ppm_get_data(shm, size, &pmap->width, &pmap->height)) |
724,19 → 1016,19 |
pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes); |
if (!pmap->data) |
return ENOMEM; |
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, |
(putpixel_cb_t)putpixel_pixmap, (void *)pm); |
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm); |
return pm; |
} |
/** Handle shared memory communication calls |
* |
* Protocol for drawing pixmaps: |
* - FB_PREPARE_SHM(client shm identification) |
* - IPC_M_AS_AREA_SEND |
* - FB_DRAW_PPM(startx,starty) |
* - FB_DRAW_PPM(startx, starty) |
* - FB_DROP_SHM |
* |
* Protocol for text drawing |
744,28 → 1036,32 |
* - FB_DRAW_TEXT_DATA |
* |
* @param callid Callid of the current call |
* @param call Current call data |
* @param vp Active viewport |
* @return 0 if the call was not handled byt this function, 1 otherwise |
* @param call Current call data |
* @param vp Active viewport |
* |
* note: this function is not threads safe, you would have |
* to redefine static variables with __thread |
* @return false if the call was not handled byt this function, true otherwise |
* |
* Note: this function is not thread-safe, you would have |
* to redefine static variables with fibril_local. |
* |
*/ |
static int |
shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
static keyfield_t *interbuffer = NULL; |
static size_t intersize = 0; |
static unsigned char *shm = NULL; |
static ipcarg_t shm_id = 0; |
static size_t shm_size; |
int handled = 1; |
int retval = 0; |
bool handled = true; |
int retval = EOK; |
viewport_t *vport = &viewports[vp]; |
unsigned int x, y; |
unsigned int x; |
unsigned int y; |
unsigned int w; |
unsigned int h; |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_SHARE_OUT: |
/* We accept one area for data interchange */ |
772,19 → 1068,21 |
if (IPC_GET_ARG1(*call) == shm_id) { |
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
shm_size = IPC_GET_ARG2(*call); |
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) |
shm = dest; |
else |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) { |
shm_id = 0; |
return false; |
} |
shm = dest; |
if (shm[0] != 'P') |
while (1) |
; |
return 1; |
return false; |
return true; |
} else { |
intersize = IPC_GET_ARG2(*call); |
receive_comm_area(callid, call, (void *) &interbuffer); |
} |
return 1; |
return true; |
case FB_PREPARE_SHM: |
if (shm_id) |
retval = EBUSY; |
799,7 → 1097,7 |
} |
shm_id = 0; |
break; |
case FB_SHM2PIXMAP: |
if (!shm) { |
retval = EINVAL; |
814,29 → 1112,36 |
} |
x = IPC_GET_ARG1(*call); |
y = IPC_GET_ARG2(*call); |
if (x > vport->width || y > vport->height) { |
if ((x > vport->width) || (y > vport->height)) { |
retval = EINVAL; |
break; |
} |
ppm_draw(shm, shm_size, IPC_GET_ARG1(*call), |
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, |
(putpixel_cb_t)putpixel, vport); |
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport); |
break; |
case FB_DRAW_TEXT_DATA: |
x = IPC_GET_ARG1(*call); |
y = IPC_GET_ARG2(*call); |
w = IPC_GET_ARG3(*call); |
h = IPC_GET_ARG4(*call); |
if (!interbuffer) { |
retval = EINVAL; |
break; |
} |
if (intersize < vport->cols * vport->rows * |
sizeof(*interbuffer)) { |
if (x + w > vport->cols || y + h > vport->rows) { |
retval = EINVAL; |
break; |
} |
draw_text_data(vport, interbuffer); |
if (intersize < w * h * sizeof(*interbuffer)) { |
retval = EINVAL; |
break; |
} |
draw_text_data(vport, interbuffer, x, y, w, h); |
break; |
default: |
handled = 0; |
handled = false; |
} |
if (handled) |
844,41 → 1149,39 |
return handled; |
} |
static void |
copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap) |
static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap) |
{ |
int y; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
int width = vport->width; |
int height = vport->height; |
unsigned int width = vport->width; |
unsigned int height = vport->height; |
if (width + vport->x > screen.xres) |
width = screen.xres - vport->x; |
if (height + vport->y > screen.yres) |
height = screen.yres - vport->y; |
realwidth = pmap->width <= width ? pmap->width : width; |
realheight = pmap->height <= height ? pmap->height : height; |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
unsigned int realwidth = pmap->width <= width ? pmap->width : width; |
unsigned int realheight = pmap->height <= height ? pmap->height : height; |
unsigned int srcrowsize = vport->width * screen.pixelbytes; |
unsigned int realrowsize = realwidth * screen.pixelbytes; |
unsigned int y; |
for (y = 0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + |
vport->x * screen.pixelbytes; |
memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp, |
realrowsize); |
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize); |
} |
} |
/** Save viewport to pixmap */ |
static int |
save_vp_to_pixmap(viewport_t *vport) |
/** Save viewport to pixmap |
* |
*/ |
static int save_vp_to_pixmap(viewport_t *vport) |
{ |
int pm; |
pixmap_t *pmap; |
pm = find_free_pixmap(); |
if (pm == -1) |
return ELIMIT; |
887,58 → 1190,60 |
pmap->data = malloc(screen.pixelbytes * vport->width * vport->height); |
if (!pmap->data) |
return ENOMEM; |
pmap->width = vport->width; |
pmap->height = vport->height; |
copy_vp_to_pixmap(vport, pmap); |
return pm; |
} |
/** Draw pixmap on screen |
* |
* @param vp Viewport to draw on |
* @param pm Pixmap identifier |
* |
*/ |
static int draw_pixmap(int vp, int pm) |
{ |
pixmap_t *pmap = &pixmaps[pm]; |
viewport_t *vport = &viewports[vp]; |
int y; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
int width = vport->width; |
int height = vport->height; |
unsigned int width = vport->width; |
unsigned int height = vport->height; |
if (width + vport->x > screen.xres) |
width = screen.xres - vport->x; |
if (height + vport->y > screen.yres) |
height = screen.yres - vport->y; |
if (!pmap->data) |
return EINVAL; |
realwidth = pmap->width <= width ? pmap->width : width; |
realheight = pmap->height <= height ? pmap->height : height; |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
unsigned int realwidth = pmap->width <= width ? pmap->width : width; |
unsigned int realheight = pmap->height <= height ? pmap->height : height; |
unsigned int srcrowsize = vport->width * screen.pixelbytes; |
unsigned int realrowsize = realwidth * screen.pixelbytes; |
unsigned int y; |
for (y = 0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + |
vport->x * screen.pixelbytes; |
memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, |
realrowsize); |
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize); |
} |
return 0; |
return EOK; |
} |
/** Tick animation one step forward */ |
static void |
anims_tick(void) |
/** Tick animation one step forward |
* |
*/ |
static void anims_tick(void) |
{ |
int i; |
unsigned int i; |
static int counts = 0; |
/* Limit redrawing */ |
945,39 → 1250,38 |
counts = (counts + 1) % 8; |
if (counts) |
return; |
for (i = 0; i < MAX_ANIMATIONS; i++) { |
if (!animations[i].animlen || !animations[i].initialized || |
!animations[i].enabled) |
if ((!animations[i].animlen) || (!animations[i].initialized) || |
(!animations[i].enabled)) |
continue; |
draw_pixmap(animations[i].vp, |
animations[i].pixmaps[animations[i].pos]); |
animations[i].pos = (animations[i].pos + 1) % |
animations[i].animlen; |
draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]); |
animations[i].pos = (animations[i].pos + 1) % animations[i].animlen; |
} |
} |
static int pointer_x, pointer_y; |
static int pointer_shown, pointer_enabled; |
static unsigned int pointer_x; |
static unsigned int pointer_y; |
static bool pointer_shown, pointer_enabled; |
static int pointer_vport = -1; |
static int pointer_pixmap = -1; |
static void |
mouse_show(void) |
static void mouse_show(void) |
{ |
int i, j; |
int visibility; |
int color; |
int bytepos; |
if (pointer_shown || !pointer_enabled) |
if ((pointer_shown) || (!pointer_enabled)) |
return; |
/* Save image under the cursor */ |
/* Save image under the pointer. */ |
if (pointer_vport == -1) { |
pointer_vport = viewport_create(pointer_x, pointer_y, |
pointer_width, pointer_height); |
pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height); |
if (pointer_vport < 0) |
return; |
} else { |
984,14 → 1288,13 |
viewports[pointer_vport].x = pointer_x; |
viewports[pointer_vport].y = pointer_y; |
} |
if (pointer_pixmap == -1) |
pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]); |
else |
copy_vp_to_pixmap(&viewports[pointer_vport], |
&pixmaps[pointer_pixmap]); |
/* Draw cursor */ |
copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]); |
/* Draw mouse pointer. */ |
for (i = 0; i < pointer_height; i++) |
for (j = 0; j < pointer_width; j++) { |
bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; |
1009,10 → 1312,10 |
pointer_shown = 1; |
} |
static void |
mouse_hide(void) |
static void mouse_hide(void) |
{ |
/* Restore image under the cursor */ |
/* Restore image under the pointer. */ |
if (pointer_shown) { |
draw_pixmap(pointer_vport, pointer_pixmap); |
pointer_shown = 0; |
1019,8 → 1322,8 |
} |
} |
static void |
mouse_move(unsigned int x, unsigned int y) |
static void mouse_move(unsigned int x, unsigned int y) |
{ |
mouse_hide(); |
pointer_x = x; |
1028,14 → 1331,14 |
mouse_show(); |
} |
static int |
anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
int handled = 1; |
int retval = 0; |
int i,nvp; |
bool handled = true; |
int retval = EOK; |
int i, nvp; |
int newval; |
switch (IPC_GET_METHOD(*call)) { |
case FB_ANIM_CREATE: |
nvp = IPC_GET_ARG1(*call); |
1125,14 → 1428,16 |
return handled; |
} |
/** Handler for messages concerning pixmap handling */ |
static int |
pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
/** Handler for messages concerning pixmap handling |
* |
*/ |
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
int handled = 1; |
int retval = 0; |
int i,nvp; |
bool handled = true; |
int retval = EOK; |
int i, nvp; |
switch (IPC_GET_METHOD(*call)) { |
case FB_VP_DRAW_PIXMAP: |
nvp = IPC_GET_ARG1(*call); |
1170,7 → 1475,7 |
default: |
handled = 0; |
} |
if (handled) |
ipc_answer_0(callid, retval); |
return handled; |
1177,35 → 1482,99 |
} |
static int rgb_from_style(attr_rgb_t *rgb, int style) |
{ |
switch (style) { |
case STYLE_NORMAL: |
rgb->fg_color = color_table[COLOR_BLACK]; |
rgb->bg_color = color_table[COLOR_WHITE]; |
break; |
case STYLE_EMPHASIS: |
rgb->fg_color = color_table[COLOR_RED]; |
rgb->bg_color = color_table[COLOR_WHITE]; |
break; |
default: |
return EINVAL; |
} |
return EOK; |
} |
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags) |
{ |
fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0); |
bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0); |
rgb->fg_color = color_table[fg_color]; |
rgb->bg_color = color_table[bg_color]; |
return EOK; |
} |
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a) |
{ |
int rc; |
switch (a->t) { |
case at_style: |
rc = rgb_from_style(rgb, a->a.s.style); |
break; |
case at_idx: |
rc = rgb_from_idx(rgb, a->a.i.fg_color, |
a->a.i.bg_color, a->a.i.flags); |
break; |
case at_rgb: |
*rgb = a->a.r; |
rc = EOK; |
break; |
} |
return rc; |
} |
static int fb_set_style(viewport_t *vport, ipcarg_t style) |
{ |
return rgb_from_style(&vport->attr, (int) style); |
} |
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags) |
{ |
return rgb_from_idx(&vport->attr, fg_color, bg_color, flags); |
} |
/** Function for handling connections to FB |
* |
*/ |
static void |
fb_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
int i; |
unsigned int row,col; |
char c; |
int vp = 0; |
viewport_t *vport = &viewports[0]; |
unsigned int vp = 0; |
viewport_t *vport = &viewports[vp]; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); /* Accept connection */ |
while (1) { |
if (vport->cursor_active || anims_enabled) |
/* Accept connection */ |
client_connected = true; |
ipc_answer_0(iid, EOK); |
while (true) { |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
unsigned int i; |
int scroll; |
wchar_t ch; |
unsigned int col, row; |
if ((vport->cursor_active) || (anims_enabled)) |
callid = async_get_call_timeout(&call, 250000); |
else |
callid = async_get_call(&call); |
mouse_hide(); |
if (!callid) { |
cursor_blink(vport); |
1213,105 → 1582,92 |
mouse_show(); |
continue; |
} |
if (shm_handle(callid, &call, vp)) |
continue; |
if (pixmap_handle(callid, &call, vp)) |
continue; |
if (anim_handle(callid, &call, vp)) |
continue; |
switch (IPC_GET_METHOD(call)) { |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
/* cleanup other viewports */ |
client_connected = false; |
/* Cleanup other viewports */ |
for (i = 1; i < MAX_VIEWPORTS; i++) |
vport->initialized = 0; |
return; /* Exit thread */ |
vport->initialized = false; |
/* Exit thread */ |
return; |
case FB_PUTCHAR: |
case FB_TRANS_PUTCHAR: |
c = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
col = IPC_GET_ARG3(call); |
if (row >= vport->rows || col >= vport->cols) { |
ch = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
row = IPC_GET_ARG3(call); |
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, EOK); |
draw_char(vport, c, row, col, vport->style, |
IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR); |
continue; /* msg already answered */ |
draw_char(vport, ch, col, row); |
/* Message already answered */ |
continue; |
case FB_CLEAR: |
clear_port(vport); |
cursor_print(vport); |
retval = 0; |
vport_clear(vport); |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_CURSOR_GOTO: |
row = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
if (row >= vport->rows || col >= vport->cols) { |
case FB_CURSOR_GOTO: |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
break; |
} |
retval = 0; |
retval = EOK; |
cursor_hide(vport); |
vport->cur_col = col; |
vport->cur_row = row; |
cursor_print(vport); |
break; |
cursor_show(vport); |
break; |
case FB_CURSOR_VISIBILITY: |
cursor_hide(vport); |
vport->cursor_active = IPC_GET_ARG1(call); |
cursor_print(vport); |
retval = 0; |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, vport->rows, vport->cols); |
ipc_answer_2(callid, EOK, vport->cols, vport->rows); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_RGB); |
continue; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if (i > vport->rows || i < (- (int)vport->rows)) { |
scroll = IPC_GET_ARG1(call); |
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) { |
retval = EINVAL; |
break; |
} |
cursor_hide(vport); |
scroll_port(vport, i*FONT_SCANLINES); |
cursor_print(vport); |
retval = 0; |
vport_scroll(vport, scroll); |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_VIEWPORT_DB: |
/* Enable double buffering */ |
i = IPC_GET_ARG1(call); |
if (i == -1) |
i = vp; |
if (i < 0 || i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (!viewports[i].initialized ) { |
retval = EADDRNOTAVAIL; |
break; |
} |
viewports[i].dboffset = 0; |
if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata) |
viewports[i].dbdata = |
malloc(screen.pixelbytes * |
viewports[i].width * viewports[i].height); |
else if (IPC_GET_ARG2(call) == 0 && |
viewports[i].dbdata) { |
free(viewports[i].dbdata); |
viewports[i].dbdata = NULL; |
} |
retval = 0; |
break; |
case FB_VIEWPORT_SWITCH: |
i = IPC_GET_ARG1(call); |
if (i < 0 || i >= MAX_VIEWPORTS) { |
if (i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (! viewports[i].initialized ) { |
if (!viewports[i].initialized) { |
retval = EADDRNOTAVAIL; |
break; |
} |
1318,11 → 1674,11 |
cursor_hide(vport); |
vp = i; |
vport = &viewports[vp]; |
cursor_print(vport); |
retval = 0; |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_VIEWPORT_CREATE: |
retval = viewport_create(IPC_GET_ARG1(call) >> 16, |
retval = vport_create(IPC_GET_ARG1(call) >> 16, |
IPC_GET_ARG1(call) & 0xffff, |
IPC_GET_ARG2(call) >> 16, |
IPC_GET_ARG2(call) & 0xffff); |
1329,34 → 1685,45 |
break; |
case FB_VIEWPORT_DELETE: |
i = IPC_GET_ARG1(call); |
if (i < 0 || i >= MAX_VIEWPORTS) { |
if (i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (! viewports[i].initialized ) { |
if (!viewports[i].initialized) { |
retval = EADDRNOTAVAIL; |
break; |
} |
viewports[i].initialized = 0; |
if (viewports[i].dbdata) { |
free(viewports[i].dbdata); |
viewports[i].dbdata = NULL; |
} |
retval = 0; |
viewports[i].initialized = false; |
if (viewports[i].bgpixel) |
free(viewports[i].bgpixel); |
if (viewports[i].backbuf) |
free(viewports[i].backbuf); |
retval = EOK; |
break; |
case FB_SET_STYLE: |
vport->style.fg_color = IPC_GET_ARG1(call); |
vport->style.bg_color = IPC_GET_ARG2(call); |
retval = 0; |
retval = fb_set_style(vport, IPC_GET_ARG1(call)); |
break; |
case FB_SET_COLOR: |
retval = fb_set_color(vport, IPC_GET_ARG1(call), |
IPC_GET_ARG2(call), IPC_GET_ARG3(call)); |
break; |
case FB_SET_RGB_COLOR: |
vport->attr.fg_color = IPC_GET_ARG1(call); |
vport->attr.bg_color = IPC_GET_ARG2(call); |
retval = EOK; |
break; |
case FB_GET_RESOLUTION: |
ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
continue; |
case FB_POINTER_MOVE: |
pointer_enabled = 1; |
pointer_enabled = true; |
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
retval = 0; |
retval = EOK; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
} |
1364,41 → 1731,33 |
} |
} |
/** Initialization of framebuffer */ |
int |
fb_init(void) |
/** Initialization of framebuffer |
* |
*/ |
int fb_init(void) |
{ |
void *fb_ph_addr; |
unsigned int fb_width; |
unsigned int fb_height; |
unsigned int fb_scanline; |
unsigned int fb_visual; |
bool fb_invert_colors; |
void *fb_addr; |
size_t asz; |
async_set_client_connection(fb_client_connection); |
fb_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
fb_width = sysinfo_value("fb.width"); |
fb_height = sysinfo_value("fb.height"); |
fb_scanline = sysinfo_value("fb.scanline"); |
fb_visual = sysinfo_value("fb.visual"); |
fb_invert_colors = sysinfo_value("fb.invert-colors"); |
asz = fb_scanline * fb_height; |
fb_addr = as_get_mappable_page(asz); |
physmem_map(fb_ph_addr, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); |
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual, |
fb_invert_colors)) |
void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
unsigned int fb_offset = sysinfo_value("fb.offset"); |
unsigned int fb_width = sysinfo_value("fb.width"); |
unsigned int fb_height = sysinfo_value("fb.height"); |
unsigned int fb_scanline = sysinfo_value("fb.scanline"); |
unsigned int fb_visual = sysinfo_value("fb.visual"); |
unsigned int fbsize = fb_scanline * fb_height; |
void *fb_addr = as_get_mappable_page(fbsize); |
if (physmem_map(fb_ph_addr + fb_offset, fb_addr, |
ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual)) |
return 0; |
return -1; |
} |
/** |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fb/ega.c |
---|
49,6 → 49,9 |
#include <ipc/ns.h> |
#include <ipc/services.h> |
#include <libarch/ddi.h> |
#include <io/style.h> |
#include <io/color.h> |
#include <sys/types.h> |
#include "ega.h" |
#include "../console/screenbuffer.h" |
61,13 → 64,14 |
saved_screen saved_screens[MAX_SAVED_SCREENS]; |
#define EGA_IO_ADDRESS 0x3d4 |
#define EGA_IO_BASE ((ioport8_t *) 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 EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR) |
#define NORMAL_COLOR ega_normal_color |
#define INVERTED_COLOR ega_inverted_color |
/* Allow only 1 connection */ |
static int client_connected = 0; |
74,13 → 78,16 |
static unsigned int scr_width; |
static unsigned int scr_height; |
static char *scr_addr; |
static uint8_t *scr_addr; |
static unsigned int style = NORMAL_COLOR; |
static unsigned int style; |
static unsigned attr_to_ega_style(const attrs_t *a); |
static uint8_t ega_glyph(wchar_t ch); |
static void clrscr(void) |
{ |
int i; |
unsigned i; |
for (i = 0; i < scr_width * scr_height; i++) { |
scr_addr[i * 2] = ' '; |
88,16 → 95,16 |
} |
} |
static void cursor_goto(unsigned int row, unsigned int col) |
static void cursor_goto(unsigned int col, unsigned int row) |
{ |
int ega_cursor; |
ega_cursor = col + scr_width * row; |
outb(EGA_IO_ADDRESS, 0xe); |
outb(EGA_IO_ADDRESS + 1, (ega_cursor >> 8) & 0xff); |
outb(EGA_IO_ADDRESS, 0xf); |
outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff); |
pio_write_8(EGA_IO_BASE, 0xe); |
pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff); |
pio_write_8(EGA_IO_BASE, 0xf); |
pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff); |
} |
static void cursor_disable(void) |
104,10 → 111,10 |
{ |
uint8_t stat; |
outb(EGA_IO_ADDRESS, 0xa); |
stat=inb(EGA_IO_ADDRESS + 1); |
outb(EGA_IO_ADDRESS, 0xa); |
outb(EGA_IO_ADDRESS + 1, stat | (1 << 5)); |
pio_write_8(EGA_IO_BASE, 0xa); |
stat = pio_read_8(EGA_IO_BASE + 1); |
pio_write_8(EGA_IO_BASE, 0xa); |
pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5)); |
} |
static void cursor_enable(void) |
114,23 → 121,24 |
{ |
uint8_t stat; |
outb(EGA_IO_ADDRESS, 0xa); |
stat=inb(EGA_IO_ADDRESS + 1); |
outb(EGA_IO_ADDRESS, 0xa); |
outb(EGA_IO_ADDRESS + 1, stat & (~(1 << 5))); |
pio_write_8(EGA_IO_BASE, 0xa); |
stat = pio_read_8(EGA_IO_BASE + 1); |
pio_write_8(EGA_IO_BASE, 0xa); |
pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5))); |
} |
static void scroll(int rows) |
{ |
int i; |
unsigned i; |
if (rows > 0) { |
memcpy(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, |
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, |
scr_width * scr_height * 2 - rows * scr_width * 2); |
for (i = 0; i < rows * scr_width; i++) |
(((short *) scr_addr) + scr_width * scr_height - rows * |
scr_width)[i] = ((style << 8) + ' '); |
} else if (rows < 0) { |
memcpy(((char *)scr_addr) - rows * scr_width * 2, scr_addr, |
memmove(((char *)scr_addr) - rows * scr_width * 2, scr_addr, |
scr_width * scr_height * 2 + rows * scr_width * 2); |
for (i = 0; i < -rows * scr_width; i++) |
((short *)scr_addr)[i] = ((style << 8 ) + ' '); |
137,22 → 145,38 |
} |
} |
static void printchar(char c, unsigned int row, unsigned int col) |
static void printchar(wchar_t c, unsigned int col, unsigned int row) |
{ |
scr_addr[(row * scr_width + col) * 2] = c; |
scr_addr[(row * scr_width + col) * 2] = ega_glyph(c); |
scr_addr[(row * scr_width + col) * 2 + 1] = style; |
cursor_goto(row, col + 1); |
cursor_goto(col + 1, row); |
} |
static void draw_text_data(keyfield_t *data) |
/** Draw text data to viewport. |
* |
* @param vport Viewport id |
* @param data Text data. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
*/ |
static void draw_text_data(keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
int i; |
unsigned int i, j; |
keyfield_t *field; |
uint8_t *dp; |
for (i = 0; i < scr_width * scr_height; i++) { |
scr_addr[i * 2] = data[i].character; |
scr_addr[i * 2 + 1] = EGA_STYLE(data[i].style.fg_color, |
data[i].style.bg_color); |
for (j = 0; j < h; j++) { |
for (i = 0; i < w; i++) { |
field = &data[j * w + i]; |
dp = &scr_addr[2 * ((y + j) * scr_width + (x + i))]; |
dp[0] = ega_glyph(field->character); |
dp[1] = attr_to_ega_style(&field->attrs); |
} |
} |
} |
181,15 → 205,72 |
return i; |
} |
static int style_to_ega_style(int style) |
{ |
unsigned int ega_style; |
switch (style) { |
case STYLE_NORMAL: |
ega_style = INVERTED_COLOR; |
break; |
case STYLE_EMPHASIS: |
ega_style = INVERTED_COLOR | 4; |
break; |
default: |
return INVERTED_COLOR; |
} |
return ega_style; |
} |
static unsigned int color_to_ega_style(int fg_color, int bg_color, int attr) |
{ |
unsigned int style; |
style = (fg_color & 7) | ((bg_color & 7) << 4); |
if (attr & CATTR_BRIGHT) |
style = style | 0x08; |
return style; |
} |
static unsigned int rgb_to_ega_style(uint32_t fg, uint32_t bg) |
{ |
return (fg > bg) ? NORMAL_COLOR : INVERTED_COLOR; |
} |
static unsigned attr_to_ega_style(const attrs_t *a) |
{ |
switch (a->t) { |
case at_style: |
return style_to_ega_style(a->a.s.style); |
case at_rgb: |
return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color); |
case at_idx: |
return color_to_ega_style(a->a.i.fg_color, |
a->a.i.bg_color, a->a.i.flags); |
default: |
return INVERTED_COLOR; |
} |
} |
static uint8_t ega_glyph(wchar_t ch) |
{ |
if (ch >= 0 && ch < 128) |
return ch; |
return '?'; |
} |
static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
char c; |
unsigned int row, col; |
int bgcolor,fgcolor; |
wchar_t c; |
unsigned int row, col, w, h; |
int bg_color, fg_color, attr; |
uint32_t bg_rgb, fg_rgb; |
keyfield_t *interbuf = NULL; |
size_t intersize = 0; |
int i; |
220,16 → 301,27 |
retval = EINVAL; |
break; |
case FB_DRAW_TEXT_DATA: |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
w = IPC_GET_ARG3(call); |
h = IPC_GET_ARG4(call); |
if (!interbuf) { |
retval = EINVAL; |
break; |
} |
draw_text_data(interbuf); |
if (col + w > scr_width || row + h > scr_height) { |
retval = EINVAL; |
break; |
} |
draw_text_data(interbuf, col, row, w, h); |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_height, scr_width); |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_INDEXED); |
continue; |
case FB_CLEAR: |
clrscr(); |
retval = 0; |
236,28 → 328,28 |
break; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
col = IPC_GET_ARG3(call); |
col = IPC_GET_ARG2(call); |
row = IPC_GET_ARG3(call); |
if (col >= scr_width || row >= scr_height) { |
retval = EINVAL; |
break; |
} |
printchar(c, row, col); |
printchar(c, col, row); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
row = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
if (row >= scr_height || col >= scr_width) { |
retval = EINVAL; |
break; |
} |
cursor_goto(row, col); |
cursor_goto(col, row); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if (i > scr_height || i < -((int) scr_height)) { |
if (i > (int) scr_height || i < -((int) scr_height)) { |
retval = EINVAL; |
break; |
} |
265,7 → 357,7 |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
if (IPC_GET_ARG1(call)) |
cursor_enable(); |
else |
cursor_disable(); |
272,11 → 364,22 |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
style = EGA_STYLE(fgcolor, bgcolor); |
style = style_to_ega_style(IPC_GET_ARG1(call)); |
retval = 0; |
break; |
case FB_SET_COLOR: |
fg_color = IPC_GET_ARG1(call); |
bg_color = IPC_GET_ARG2(call); |
attr = IPC_GET_ARG3(call); |
style = color_to_ega_style(fg_color, bg_color, attr); |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
fg_rgb = IPC_GET_ARG1(call); |
bg_rgb = IPC_GET_ARG2(call); |
style = rgb_to_ega_style(fg_rgb, bg_rgb); |
retval = 0; |
break; |
case FB_VP_DRAW_PIXMAP: |
i = IPC_GET_ARG2(call); |
retval = print_screen(i); |
296,9 → 399,12 |
} |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
retval = EINVAL; |
} |
ipc_answer_0(callid, retval); |
} |
312,13 → 418,22 |
ega_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
scr_width = sysinfo_value("fb.width"); |
scr_height = sysinfo_value("fb.height"); |
iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2); |
if (sysinfo_value("fb.blinking")) { |
ega_normal_color &= 0x77; |
ega_inverted_color &= 0x77; |
} |
style = NORMAL_COLOR; |
iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2); |
sz = scr_width * scr_height * 2; |
scr_addr = as_get_mappable_page(sz); |
physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); |
if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
async_set_client_connection(ega_client_connection); |
326,6 → 441,6 |
} |
/** |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fb/ppm.c |
---|
89,26 → 89,26 |
{ |
unsigned int width, height; |
unsigned int maxcolor; |
int i; |
unsigned int i; |
unsigned int color; |
unsigned int coef; |
/* Read magic */ |
if (data[0] != 'P' || data[1] != '6') |
if ((data[0] != 'P') || (data[1] != '6')) |
return EINVAL; |
data+=2; |
data += 2; |
skip_whitespace(&data); |
read_num(&data, &width); |
skip_whitespace(&data); |
read_num(&data,&height); |
read_num(&data, &height); |
skip_whitespace(&data); |
read_num(&data,&maxcolor); |
read_num(&data, &maxcolor); |
data++; |
if (maxcolor == 0 || maxcolor > 255 || width * height > datasz) { |
if ((maxcolor == 0) || (maxcolor > 255) || (width * height > datasz)) |
return EINVAL; |
} |
coef = 255 / maxcolor; |
if (coef * maxcolor > 255) |
coef -= 1; |
125,6 → 125,6 |
(*putpixel)(vport, sx + (i % width), sy + (i / width), color); |
data += 3; |
} |
return 0; |
} |
/branches/arm/uspace/srv/fb/ega.h |
---|
27,10 → 27,10 |
*/ |
/** @addtogroup egafb |
* @brief HelenOS EGA framebuffer. |
* @brief HelenOS EGA framebuffer. |
* @ingroup fbs |
* @{ |
*/ |
*/ |
/** @file |
*/ |
43,4 → 43,3 |
/** @} |
*/ |
/branches/arm/uspace/srv/fb/serial_console.h |
---|
0,0 → 1,56 |
/* |
* 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_ |
#include <ipc/ipc.h> |
typedef void (*putc_function_t)(char); |
void serial_puts(char *str); |
void serial_goto(const unsigned int col, const unsigned int row); |
void serial_clrscr(void); |
void serial_scroll(int i); |
void serial_cursor_disable(void); |
void serial_cursor_enable(void); |
void serial_set_scroll_region(unsigned height); |
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h); |
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall); |
#endif |
/branches/arm/uspace/srv/fb/Makefile |
---|
31,12 → 31,11 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
LIBS = $(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
45,27 → 44,45 |
main.c \ |
ppm.c |
ifneq ($(ARCH), ia64) |
ifneq ($(UARCH),ia64) |
SOURCES += fb.c \ |
font-8x16.c |
CFLAGS += -DFB_ENABLED |
endif |
ifeq ($(ARCH), ia32) |
ifeq ($(UARCH),ia32) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), amd64) |
ifeq ($(UARCH),ia64) |
SOURCES += ega.c \ |
ski.c \ |
serial_console.c |
CFLAGS += -DSKI_ENABLED |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(UARCH),amd64) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), mips32) |
SOURCES += msim.c |
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN |
ifeq ($(UARCH),mips32) |
SOURCES += msim.c \ |
serial_console.c |
CFLAGS += -DMSIM_ENABLED |
endif |
CFLAGS += -D$(ARCH) |
ifeq ($(UARCH),sparc64) |
SOURCES += sgcn.c \ |
serial_console.c |
CFLAGS += -DSGCN_ENABLED |
endif |
CFLAGS += -D$(UARCH) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
75,18 → 92,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/fb/font-8x16.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2000 Dmitry Bolkhovityanov |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
26,4616 → 27,3245 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#include <sys/types.h> |
#include "font-8x16.h" |
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = { |
/** Convert character to font glyph index |
* |
* The font does not cover all Unicode characters. |
* This function converts the character to an appropriate |
* glyph in the font or returns an index to the question |
* mark glyph if no specific glyph exists. |
*/ |
uint16_t fb_font_glyph(const wchar_t ch) |
{ |
if (ch == 0x0000) |
return 0; |
if ((ch >= 0x0020) && (ch <= 0x007f)) |
return (ch - 32); |
if ((ch >= 0x00a0) && (ch <= 0x021f)) |
return (ch - 64); |
if ((ch >= 0x0222) && (ch <= 0x0233)) |
return (ch - 66); |
if ((ch >= 0x0250) && (ch <= 0x02ad)) |
return (ch - 94); |
if ((ch >= 0x02b0) && (ch <= 0x02cf)) |
return (ch - 96); |
if ((ch >= 0x02d8) && (ch <= 0x02dd)) |
return (ch - 104); |
if (ch == 0x02ee) |
return 630; |
if ((ch >= 0x0300) && (ch <= 0x0301)) |
return (ch - 137); |
if (ch == 0x0303) |
return 633; |
if (ch == 0x0309) |
return 634; |
if ((ch >= 0x0312) && (ch <= 0x0314)) |
return (ch - 151); |
if (ch == 0x0323) |
return 638; |
if ((ch >= 0x0340) && (ch <= 0x0341)) |
return (ch - 193); |
if ((ch >= 0x0374) && (ch <= 0x0375)) |
return (ch - 243); |
if (ch == 0x037a) |
return 643; |
if (ch == 0x037e) |
return 644; |
if ((ch >= 0x0384) && (ch <= 0x038a)) |
return (ch - 255); |
if (ch == 0x038c) |
return 652; |
if ((ch >= 0x038e) && (ch <= 0x03a1)) |
return (ch - 257); |
if ((ch >= 0x03a3) && (ch <= 0x03ce)) |
return (ch - 258); |
if ((ch >= 0x03d0) && (ch <= 0x03d7)) |
return (ch - 259); |
if ((ch >= 0x03da) && (ch <= 0x03f3)) |
return (ch - 261); |
if ((ch >= 0x0400) && (ch <= 0x0486)) |
return (ch - 273); |
if ((ch >= 0x0488) && (ch <= 0x04ce)) |
return (ch - 274); |
if ((ch >= 0x04d0) && (ch <= 0x04f5)) |
return (ch - 275); |
if ((ch >= 0x04f8) && (ch <= 0x04f9)) |
return (ch - 277); |
if ((ch >= 0x0500) && (ch <= 0x050f)) |
return (ch - 283); |
if ((ch >= 0x0530) && (ch <= 0x0556)) |
return (ch - 315); |
if ((ch >= 0x0559) && (ch <= 0x055f)) |
return (ch - 317); |
if ((ch >= 0x0561) && (ch <= 0x0587)) |
return (ch - 318); |
if ((ch >= 0x0589) && (ch <= 0x058a)) |
return (ch - 319); |
if ((ch >= 0x0591) && (ch <= 0x05a1)) |
return (ch - 325); |
if ((ch >= 0x05a3) && (ch <= 0x05b9)) |
return (ch - 326); |
if ((ch >= 0x05bb) && (ch <= 0x05c4)) |
return (ch - 327); |
if ((ch >= 0x05d0) && (ch <= 0x05ea)) |
return (ch - 338); |
if ((ch >= 0x05f0) && (ch <= 0x05f4)) |
return (ch - 343); |
if (ch == 0x060c) |
return 1182; |
if (ch == 0x061b) |
return 1183; |
if (ch == 0x061f) |
return 1184; |
if ((ch >= 0x0621) && (ch <= 0x063a)) |
return (ch - 384); |
if ((ch >= 0x0640) && (ch <= 0x0655)) |
return (ch - 389); |
if ((ch >= 0x0660) && (ch <= 0x066d)) |
return (ch - 399); |
if ((ch >= 0x0670) && (ch <= 0x06ed)) |
return (ch - 401); |
if ((ch >= 0x06f0) && (ch <= 0x06fe)) |
return (ch - 403); |
if (ch == 0x10d3) |
return 1388; |
if (ch == 0x10d7) |
return 1389; |
if (ch == 0x10da) |
return 1390; |
if (ch == 0x10dd) |
return 1391; |
if (ch == 0x10e6) |
return 1392; |
if ((ch >= 0x1e00) && (ch <= 0x1e9b)) |
return (ch - 6287); |
if ((ch >= 0x1ea0) && (ch <= 0x1ef9)) |
return (ch - 6291); |
if ((ch >= 0x1f00) && (ch <= 0x1f07)) |
return (ch - 6297); |
if ((ch >= 0x2000) && (ch <= 0x2027)) |
return (ch - 6545); |
if ((ch >= 0x2030) && (ch <= 0x2046)) |
return (ch - 6553); |
if ((ch >= 0x2048) && (ch <= 0x204d)) |
return (ch - 6554); |
if (ch == 0x2070) |
return 1716; |
if ((ch >= 0x2074) && (ch <= 0x208f)) |
return (ch - 6591); |
if ((ch >= 0x20a0) && (ch <= 0x20af)) |
return (ch - 6607); |
if ((ch >= 0x2100) && (ch <= 0x213a)) |
return (ch - 6687); |
if ((ch >= 0x2153) && (ch <= 0x2183)) |
return (ch - 6711); |
if ((ch >= 0x2190) && (ch <= 0x21f3)) |
return (ch - 6723); |
if ((ch >= 0x2200) && (ch <= 0x22f1)) |
return (ch - 6735); |
if (ch == 0x2300) |
return 2211; |
if (ch == 0x2302) |
return 2212; |
if ((ch >= 0x2308) && (ch <= 0x230b)) |
return (ch - 6755); |
if (ch == 0x2310) |
return 2217; |
if (ch == 0x2318) |
return 2218; |
if ((ch >= 0x231a) && (ch <= 0x231b)) |
return (ch - 6767); |
if ((ch >= 0x2320) && (ch <= 0x2321)) |
return (ch - 6771); |
if ((ch >= 0x2329) && (ch <= 0x232a)) |
return (ch - 6778); |
if ((ch >= 0x239b) && (ch <= 0x23bd)) |
return (ch - 6890); |
if (ch == 0x23ce) |
return 2260; |
if ((ch >= 0x2409) && (ch <= 0x240d)) |
return (ch - 6964); |
if ((ch >= 0x2423) && (ch <= 0x2424)) |
return (ch - 6985); |
if (ch == 0x2426) |
return 2268; |
if ((ch >= 0x2500) && (ch <= 0x2595)) |
return (ch - 7203); |
if ((ch >= 0x25a0) && (ch <= 0x25f7)) |
return (ch - 7213); |
if ((ch >= 0x2600) && (ch <= 0x2602)) |
return (ch - 7221); |
if ((ch >= 0x2605) && (ch <= 0x260d)) |
return (ch - 7223); |
if ((ch >= 0x2610) && (ch <= 0x2613)) |
return (ch - 7225); |
if (ch == 0x2620) |
return 2523; |
if (ch == 0x2622) |
return 2524; |
if (ch == 0x2626) |
return 2525; |
if ((ch >= 0x2628) && (ch <= 0x262b)) |
return (ch - 7242); |
if ((ch >= 0x262e) && (ch <= 0x2637)) |
return (ch - 7244); |
if ((ch >= 0x2639) && (ch <= 0x2653)) |
return (ch - 7245); |
if ((ch >= 0x2660) && (ch <= 0x2667)) |
return (ch - 7257); |
if ((ch >= 0x2669) && (ch <= 0x266f)) |
return (ch - 7258); |
if ((ch >= 0xfb00) && (ch <= 0xfb05)) |
return (ch - 61674); |
if ((ch >= 0xfb50) && (ch <= 0xfbb1)) |
return (ch - 61748); |
if ((ch >= 0xfbd3) && (ch <= 0xfbe9)) |
return (ch - 61781); |
if ((ch >= 0xfbfc) && (ch <= 0xfbff)) |
return (ch - 61799); |
if ((ch >= 0xfc5b) && (ch <= 0xfc63)) |
return (ch - 61890); |
if (ch == 0xfc90) |
return 2722; |
if ((ch >= 0xfcf2) && (ch <= 0xfcf4)) |
return (ch - 62031); |
if ((ch >= 0xfd3c) && (ch <= 0xfd3f)) |
return (ch - 62102); |
if (ch == 0xfdf2) |
return 2730; |
if ((ch >= 0xfe50) && (ch <= 0xfe52)) |
return (ch - 62373); |
if ((ch >= 0xfe54) && (ch <= 0xfe66)) |
return (ch - 62374); |
if ((ch >= 0xfe68) && (ch <= 0xfe6b)) |
return (ch - 62375); |
if ((ch >= 0xfe70) && (ch <= 0xfe72)) |
return (ch - 62379); |
if (ch == 0xfe74) |
return 2760; |
if ((ch >= 0xfe76) && (ch <= 0xfefc)) |
return (ch - 62381); |
if (ch == 0xfeff) |
return 2896; |
return 2898; |
} |
/* 0 0x00 '^@' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = { |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00}, |
{0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x44, 0xba, 0xb2, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00}, |
{0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00}, |
{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00}, |
{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x3c, 0x42, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0xec, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0x1c, 0x3c, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x7c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x0c, 0x18, 0x0e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x0c, 0x18, 0x0e, 0x00}, |
{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x30, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x6c, 0x38, 0x10, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x6c, 0x38, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x18, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x10, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xff, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7e, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7e, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0x3c, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x3c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00}, |
{0x18, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf7, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x7b, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x66, 0x3c, 0x00}, |
{0x08, 0x1c, 0x22, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x0e, 0x1b, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x30, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30}, |
{0x6c, 0x38, 0x10, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x36, 0x36, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x78, 0xe0, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x30}, |
{0x6c, 0x38, 0x10, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x60, 0x60, 0xc0, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x30}, |
{0x6c, 0x38, 0x10, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x18, 0x0c, 0x38, 0x00}, |
{0x6c, 0x38, 0x10, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x38, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x60, 0x38, 0x00}, |
{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xf8, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x64, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xe6, 0xe6, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xe0, 0xe0, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xb6, 0xb3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x4c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0x4c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x18, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0xfe, 0xcc, 0x8c, 0x2c, 0x3c, 0x2c, 0x0c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x00}, |
{0x00, 0x00, 0x1c, 0x36, 0x32, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00}, |
{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x38, 0x6c, 0x38, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x6d, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc8, 0x38, 0x70, 0xd0, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0xec, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00}, |
{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x6c, 0xe6, 0x06, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x38, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x0c, 0x38, 0x60, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x0c, 0x6c, 0x38, 0x00}, |
{0x00, 0x00, 0x7e, 0xfe, 0x9a, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x36, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00}, |
{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x63, 0xb3, 0xb3, 0x33, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x0d, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0xf0, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x7e, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0xfc, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x78, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x7c, 0xc0, 0xc6, 0x7c, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x7e, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x60, 0x60, 0x78, 0x0c, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x78, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x18, 0x4c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x1b, 0x0e, 0x04, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf5, 0xda, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3d, 0x1a, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xcb, 0xf6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x67, 0x6f, 0xff, 0x03, 0x1b, 0x0e, 0x00}, |
{0x00, 0x00, 0xe3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x63, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xf8, 0xff, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x00, 0xb7, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00}, |
{0x6c, 0x38, 0x10, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x00, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x28, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x78, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x00, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x30, 0x30, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xdf, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x3e, 0xcc, 0x78, 0x00}, |
{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x6c, 0x38, 0x10, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x6c, 0x38, 0x10, 0xfe, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00}, |
{0x00, 0x1b, 0x0e, 0x04, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0xd8, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x00}, |
{0x60, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x3c, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x30}, |
{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x1c, 0x74, 0x06, 0x06, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0e, 0x3c, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xdc, 0xe6, 0x7c, 0x80, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0d, 0x06, 0x00}, |
{0x00, 0x00, 0x06, 0x0d, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6c, 0x8e, 0x16, 0x26, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xcd, 0x0d, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xdc, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x06, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x64, 0x28, 0x38, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xdc, 0x6c, 0x0c, 0x0c, 0x0e, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x7b, 0xde, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x78, 0x58, 0x3e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7f, 0x63, 0x66, 0x6c, 0x7e, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x6c, 0x0c, 0x0d, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x6c, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xfc, 0xc0, 0xd8, 0x70, 0x00}, |
{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0xd8, 0x70, 0x00}, |
{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x98, 0xd8, 0x70, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0xd8, 0x70, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x3b, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x06, 0x06, 0x03, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xcb, 0xfe, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x7e, 0xc7, 0x7c, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x76, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7e, 0xcc, 0x78, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0x6c, 0x3c, 0x3c, 0x6c, 0xcc, 0x0c, 0x0c, 0x0e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0xfc, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xdb, 0xdb, 0xde, 0xde, 0xdb, 0x6b, 0x03, 0x1b, 0x0e, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xdb, 0xdd, 0x6f, 0x04, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0x36, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x26, 0x6d, 0x6c, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x2c, 0x18, 0x00}, |
{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x6c, 0x6e, 0x6d, 0x36, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0xc0, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x03, 0x0e, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0xf6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6f, 0x6b, 0x63, 0x66, 0x6c, 0x6d, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xb0, 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xd8, 0xd8, 0xf0, 0xd8, 0xd8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xd8, 0xd8, 0x78, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0xc0, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x70, 0xc0, 0x70, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0x70, 0x18, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x20, 0x20, 0x70, 0x70, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xd8, 0xd8, 0x70, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1c, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x6c, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, |
{0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x3e, 0x32, 0x30, 0x34, 0x3c, 0x34, 0x30, 0x30, 0x32, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x82, 0x44, 0x7c, 0x44, 0x00, 0x82, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x30, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x46, 0x7c, 0x18, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0x20, 0x30, 0x10, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x6c, 0x3c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x46, 0x2c, 0x2c, 0x18, 0x30, 0x68, 0x68, 0xc4, 0xc2, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x1e, 0xc6, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0xc0, 0x21, 0x32, 0x12, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x0c, 0x18, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x06, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x32, 0x30, 0x30, 0x3c, 0x34, 0x30, 0x30, 0x30, 0x30, 0x00}, |
{0x00, 0x60, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x06, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x60, 0x60, 0xfe, 0xfe, 0x0c, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xac, 0x26, 0x26, 0x0b, 0x0b, 0x1b, 0x1b, 0x1b, 0x1b, 0x03, 0x02, 0x04, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x28, 0x4c, 0x14, 0x24, 0x06, 0x02, 0x02, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x7e, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xd6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x76, 0x9c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0xd6, 0x66, 0x06, 0x06, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x3c, 0x60, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x26, 0x1c, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0x68, 0x38, 0x30, 0x38, 0x38, 0x4c, 0x4c, 0x86, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xba, 0x30, 0x38, 0x28, 0x4c, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xc0, 0xcc, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xdc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x7e, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x1c, 0x18, 0x7e, 0x58, 0x18, 0x18, 0x18, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0x60, 0x3c, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x03, 0x06, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xf8, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x18, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xb0, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xf8, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xce, 0xdb, 0xd9, 0xd8, 0xfe, 0xd8, 0xd8, 0xd9, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xdb, 0xd8, 0xfe, 0xd8, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x7c, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x88, 0x8c, 0x9c, 0x96, 0xf6, 0xb6, 0xbf, 0xab, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x8c, 0x9c, 0xf6, 0xbe, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xa3, 0xb2, 0x96, 0xfc, 0x9c, 0xbe, 0xaa, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa3, 0x96, 0xfe, 0xab, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00}, |
{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0x86, 0x06, 0x7c, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc2, 0xc6, 0xc6, 0xc4, 0xcc, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0x66, 0x00, 0xc2, 0xc6, 0xc4, 0xc4, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0x66, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00}, |
{0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00}, |
{0x04, 0x7c, 0x40, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x7c, 0x40, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x0c, 0x0c, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0x78, 0x18, 0x18, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x3c, 0x0f, 0x18, 0x18, 0xf0, 0x3c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x40, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x7c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0xc3, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x50, 0x46, 0x00, 0x82, 0x41, 0x00, 0x62, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0xf0, 0x00}, |
{0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0xf8, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x78, 0x6c, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0xf6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0xf0, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf3, 0xb3, 0xb3, 0x36, 0x3c, 0x3c, 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xb6, 0xbc, 0x3c, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xd8, 0xf8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xf8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00}, |
{0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3c, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00}, |
{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcd, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x8c, 0x0c, 0x38, 0x0d, 0x0d, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x0c, 0x39, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0xcd, 0xcd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xfd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xce, 0xc6, 0xc6, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x64, 0x94, 0xba, 0x52, 0x4c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xcf, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0x7f, 0x24, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0xf0, 0x3c, 0x0e, 0x04, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x30, 0x60, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1e, 0x0e, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x30, 0x18, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x63, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd0, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x06, 0x3c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x0c, 0x18, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xcf, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0xc0, 0x00}, |
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xca, 0xc0, 0xc0, 0xc0, 0x00}, |
{0x00, 0x00, 0x60, 0x38, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x1c, 0x0c, 0x18, 0x3c, 0x64, 0x66, 0x62, 0x63, 0x3d, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0f, 0x00}, |
{0x00, 0x00, 0x0e, 0x18, 0x30, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0f, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7e, 0x06, 0x06, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1c, 0x18, 0x30, 0x60, 0x3e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xfe, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0x77, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x6c}, |
{0x18, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x38, 0x10, 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x60, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0c, 0x00}, |
{0x10, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x74, 0xd6, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xc0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x18, 0x30, 0x00}, |
{0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1b, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x44, 0xaa, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x0a, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x40, 0x50, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x6c, 0xd8, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x08, 0x30}, |
{0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x40, 0xa0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x10, 0x10}, |
{0x18, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x00}, |
{0x48, 0xa8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x33, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x06, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x60, 0x66, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18}, |
{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x03, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x76, 0xdc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x36, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xcc, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xf8, 0x4c, 0xcc, 0xcc, 0xec, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x46, 0xc6, 0xc6, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x6c, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x34, 0x18, 0x0c, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x66, 0x64, 0x6c, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xf6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xc6, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00, 0x00}, |
{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00}, |
{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00}, |
{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00}, |
{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x01, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x10, 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x0c, 0x10}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x20, 0x40, 0x30, 0x10, 0x20, 0x42, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xf8, 0x78, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x91, 0x92, 0x64, 0x08, 0x10, 0x26, 0x49, 0x89, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x18, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x06, 0x28, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x06, 0x28, 0x5e, 0x00, 0x00, 0x00}, |
{0x00, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x04, 0x03, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x04, 0x03, 0x04, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x04, 0x03, 0x04, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00}, |
{0x06, 0x08, 0x06, 0x08, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x08, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x00, 0x08, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x1c, 0x6a, 0x04, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x14, 0x08, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x12, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x15, 0x88, 0x88, 0x8a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x00, 0x0a, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x90, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x2a, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x00, 0x50, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00}, |
{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x20, 0x40, 0x3e, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x01, 0x02, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x44, 0x09, 0xa2, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x08, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x02, 0x2a, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x14, 0x00, 0x08, 0x00}, |
{0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x40, 0x38, 0x40, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x12, 0x2c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x20, 0x47, 0x88, 0x08, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x50, 0x20, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x08}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x80, 0x60, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x40, 0x40, 0x43, 0x55, 0x7e, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x2a, 0x20, 0x26, 0x2a, 0x7c, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x0e, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x14, 0x08, 0x14, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x2c, 0x10, 0x28, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x15, 0x8a, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x5a, 0xa5, 0x66, 0x5b, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x5a, 0x66, 0xa5, 0x5a, 0x00}, |
{0x00, 0x00, 0x18, 0x66, 0x42, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x42, 0x66, 0x18, 0x00, 0x00}, |
{0x08, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x26, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x0c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8a, 0x90, 0x60}, |
{0x32, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x0c, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x54, 0xaa, 0x92, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x82, 0xfe, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x14, 0x08}, |
{0x08, 0x14, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x10, 0x10, 0x10}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x4e, 0xf0, 0xfe, 0x7c, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x92, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x60, 0x7e, 0x3c, 0x30, 0x60, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x54, 0x54, 0x54, 0x54, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x4c, 0x30, 0x4c, 0x02, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0xaa, 0xaa, 0xaa, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x44, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0x38}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x38, 0x6c, 0x38}, |
{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x0c, 0xec, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x7c, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x30, 0x30, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x60, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x30, 0x18, 0x70, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x18, 0x70, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00}, |
{0x60, 0x30, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x76, 0xdc, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00}, |
{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00}, |
{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00}, |
{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x0c, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x60, 0x30, 0xe0, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x30, 0x18, 0x70, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x6c, 0x38, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x6c, 0x38, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00}, |
{0x0c, 0x18, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x0c, 0xec, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x7c, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x7c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00}, |
{0x0c, 0x18, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x30, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x10, 0x38, 0x6c, 0x00}, |
{0x0c, 0x18, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00}, |
{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x60, 0x6c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x60, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x18, 0x18, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x06, 0x16, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x7e, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x08, 0x1c, 0x36, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x6c, 0x6c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x6c, 0x6c, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x76, 0xdc, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00}, |
{0x0c, 0x18, 0x72, 0x9c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x18, 0x18, 0x00}, |
{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x30, 0x30, 0x00}, |
{0x30, 0x30, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x10, 0x38, 0x44, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00}, |
{0x6c, 0x6c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x18, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x38, 0x0c, 0x18, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x16, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x16, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0xc0, 0x68, 0x1c, 0x36, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0xc0, 0x68, 0x1c, 0x36, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x28, 0x54, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x38, 0x44, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x0c, 0x18, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x18, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x30, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x08, 0x54, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x08, 0x54, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x72, 0x9c, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x72, 0x9c, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x38, 0x0c, 0x18, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x23, 0x76, 0x88, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xc4, 0x6e, 0x11, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x38, 0x44, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x38, 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x38, 0x0c, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x23, 0x76, 0x88, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xc4, 0x6e, 0x11, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x28, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x18, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x63, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x70, 0x1b, 0x33, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x68, 0xb3, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x68, 0xb3, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x38, 0x0c, 0x18, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x63, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x70, 0x1b, 0x33, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x68, 0xb3, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x68, 0xb3, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00}, |
{0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0c, 0x18, 0xf6, 0x06, 0x00}, |
{0x38, 0x0c, 0x18, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x38, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x3a, 0x5c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00}, |
{0x00, 0x18, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x60, 0x6c, 0xc6, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xcc, 0x66, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x60, 0x66, 0xcc, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc6, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x34, 0x58, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x34, 0x58, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0xfe, 0x00, 0xa4, 0xaa, 0xea, 0xea, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xa4, 0xea, 0xaa, 0xaa, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x8a, 0xce, 0x8e, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x8e, 0xca, 0x8a, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xca, 0x2e, 0x4a, 0x2a, 0xca, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xaa, 0xae, 0xea, 0x2a, 0x2a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0x6a, 0x8e, 0xca, 0xaa, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0x38, 0x20, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0x30, 0x28, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x4a, 0x4e, 0x4a, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0x28, 0x28, 0x38, 0x28, 0x28, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0xa2, 0xa2, 0xe2, 0xea, 0xa4, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x08, 0x08, 0x08, 0x28, 0x10, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0x80, 0x80, 0x80, 0xf0, 0x28, 0x30, 0x28, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00}, |
{0xfe, 0x00, 0xc0, 0xa0, 0xc0, 0xa0, 0x20, 0x20, 0x38, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x9c, 0xd2, 0xbc, 0x92, 0x9c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00}, |
{0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x66, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00}, |
{0x00, 0xcc, 0xcc, 0xcc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x38, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xc3, 0xdb, 0x1b, 0x1e, 0x1c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x7c, 0x00, 0x00}, |
{0x7c, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x38, 0x6c, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x28, 0x00, 0x00, 0x44, 0xee, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7b, 0xcf, 0xcf, 0x1b, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xde, 0xf3, 0xf3, 0xc6, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x06, 0x06, 0x0c, 0x0c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x3e, 0x72, 0xf2, 0xf2, 0xf2, 0x72, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xf8, 0x9c, 0x9e, 0x9e, 0x9e, 0x9c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcf, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x04, 0x7c, 0xce, 0xc8, 0xc8, 0xd0, 0xd0, 0xd0, 0xe0, 0xe6, 0x7c, 0x40, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xd6, 0xd8, 0xd8, 0xd8, 0xde, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xf0, 0xcd, 0xce, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x60, 0xf8, 0x60, 0xf8, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x02, 0xec, 0xd6, 0xde, 0xd6, 0xd6, 0xf6, 0xd6, 0x40, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x66, 0x76, 0xff, 0x76, 0x6e, 0xff, 0x6e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xf8, 0xe0, 0xf3, 0xd6, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x81, 0x81, 0x81, 0x5a, 0xff, 0x5a, 0xff, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xf2, 0x8a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa2, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x36, 0x60, 0xfc, 0x60, 0xf8, 0x60, 0x60, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0xfe, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x1e, 0x78, 0x1e, 0x78, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x7c, 0xb6, 0x36, 0x33, 0x33, 0x33, 0x63, 0x66, 0xf6, 0xdc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x98, 0x18, 0x0e, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x8c, 0x06, 0x1c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x62, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x4e, 0xb9, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x7c, 0xda, 0xd8, 0xd8, 0xda, 0x7c, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x6e, 0xdb, 0x9b, 0x1b, 0x0e, 0x00, 0x00, 0x00}, |
{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x7b, 0xdb, 0x9b, 0x1b, 0x0d, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x86, 0x26, 0x3e, 0x26, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7f, 0xb9, 0x58, 0x1a, 0x1e, 0x1a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x66, 0x46, 0x87, 0x8c, 0x8c, 0x7c, 0x98, 0x98, 0x70, 0x00}, |
{0x00, 0x00, 0x52, 0xb5, 0x15, 0x16, 0x2c, 0x34, 0x68, 0xa9, 0xaa, 0x4c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x48, 0xb0, 0x80, 0x48, 0x7c, 0x66, 0x26, 0x26, 0xa6, 0x46, 0x06, 0x34, 0x48, 0x00}, |
{0x00, 0x00, 0xe2, 0xa2, 0xa2, 0xa2, 0xbe, 0xa2, 0xa2, 0xa2, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x36, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x1e, 0x18, 0x76, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x33, 0x4e, 0x06, 0x06, 0x0c, 0x0c, 0x1f, 0x6c, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x71, 0x8e, 0x04, 0x0c, 0x06, 0x03, 0x63, 0xc3, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x46, 0x49, 0x39, 0x1e, 0x18, 0x30, 0x70, 0xb1, 0xba, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0e, 0x19, 0x31, 0x32, 0x64, 0x68, 0x70, 0xe1, 0x66, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd8, 0xff, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe2, 0xa2, 0xb2, 0xb2, 0xaa, 0xaa, 0xa6, 0xa6, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xcc, 0xcf, 0xed, 0xff, 0xfc, 0xdf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5, 0xb9, 0xa1, 0xa1, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x93, 0xa3, 0x63, 0x4b, 0x6a, 0xa4, 0xb0, 0xb0, 0x60, 0x00}, |
{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xaa, 0xa6, 0x7e, 0x01, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x4d, 0x4d, 0x19, 0x1e, 0x1c, 0x34, 0x34, 0xb5, 0x62, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x58, 0xa6, 0xa3, 0x6c, 0xb8, 0x26, 0x26, 0x26, 0xa7, 0xc2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xb0, 0xa8, 0xa4, 0xe2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x6d, 0x67, 0x66, 0xee, 0x08, 0x00, 0x00, 0x00}, |
{0x30, 0x0c, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xdc, 0xdc, 0xe6, 0xe6, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x71, 0xdb, 0x35, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x52, 0x5a, 0x52, 0x5f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf1, 0x5b, 0x55, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x18, 0xce, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0x6c, 0x38, 0x50, 0x40, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x0a, 0x14, 0x14, 0x28, 0x28, 0x50, 0x50, 0xa0, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x9c, 0x30, 0xfe, 0x0c, 0x18, 0x38, 0x0c, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00}, |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x26, 0x03, 0x13, 0x0c, 0x13, 0x03, 0x03, 0x66, 0x98, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x6c, 0x38, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x2d, 0x2d, 0x1a, 0x1e, 0x1b, 0x31, 0x31, 0xb2, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x14, 0x6b, 0xc8, 0xcc, 0xc6, 0xc6, 0xcc, 0xc0, 0x63, 0x1c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xe7, 0xff, 0xe0, 0x67, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x44, 0xf8, 0xc0, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x4c, 0x52, 0x3c, 0x10, 0x3c, 0x60, 0xc0, 0xc3, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x73, 0xce, 0x18, 0x3a, 0x5c, 0x18, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x2c, 0x3c, 0x2c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x12, 0x12, 0x12, 0x16, 0x36, 0x3e, 0x3a, 0x5a, 0x52, 0x91, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x46, 0xc6, 0xc4, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x42, 0xc6, 0xe7, 0x7a, 0x38, 0x5c, 0xce, 0xe7, 0x63, 0xe2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xfc, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x7e, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x40, 0x78, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x7e, 0xf2, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xfe, 0x7e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xff, 0x83, 0x86, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0x30, 0x70, 0xb2, 0xf6, 0x3c, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xf0, 0xc0, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xf0, 0x80, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xf0, 0x30, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x95, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xdb, 0xdb, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x15, 0x15, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x65, 0x65, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x5a, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xcc, 0xe6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0xcc, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x5a, 0x99, 0xbd, 0xdb, 0xdb, 0xbd, 0x99, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x62, 0xff, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x26, 0xff, 0x46, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xce, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x73, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xff, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0xff, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xfc, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x3f, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x63, 0xff, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xff, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x33, 0x63, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0xc6, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x3b, 0x6b, 0xfe, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x60, 0xdc, 0xd6, 0x7f, 0x16, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x5a, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x6e, 0xff, 0x76, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x16, 0x1c, 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x66, 0x36, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xcc, 0xd8, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, 0xcc, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x1e, 0x1c, 0x16, 0x03, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x78, 0x38, 0x68, 0xc0, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x2e, 0x3f, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x7e, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xff, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7f, 0xc4, 0x7f, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x7e, 0xcb, 0x7e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfe, 0x23, 0xfe, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7f, 0xc0, 0x7f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0x03, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0xc3, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0xd8, 0xec, 0xb6, 0x1b, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x1b, 0x37, 0x6d, 0xd8, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x20, 0x30, 0xd8, 0x6d, 0x37, 0x1b, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x0c, 0x1b, 0xb6, 0xec, 0xd8, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x60, 0xff, 0x60, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x06, 0xff, 0x06, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6a, 0xff, 0x65, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa6, 0xff, 0x56, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xd5, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0x66, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xab, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x41, 0x81, 0x41, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x82, 0x81, 0x82, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x7c, 0x00, 0x7c, 0x44, 0x7c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x7c, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x54, 0xd6, 0x54, 0x54, 0x54, 0xd6, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xe8, 0xbc, 0x82, 0x81, 0x82, 0xbc, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x80, 0xbc, 0xb8, 0xac, 0x86, 0x83, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x01, 0x81, 0xc1, 0x61, 0x35, 0x1d, 0x3d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x06, 0x06, 0x3e, 0x66, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x7e, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0xfe, 0x16, 0x16, 0x16, 0x7e, 0x16, 0x26, 0x26, 0x26, 0xfe, 0x40, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x3e, 0x66, 0xcf, 0xdb, 0xdb, 0xf3, 0x66, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x3e, 0x64, 0xc8, 0xc8, 0xfe, 0xc8, 0xd0, 0x70, 0x3e, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfe, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0x06, 0xfe, 0x06, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0xf8, 0x1c, 0x16, 0x26, 0xfe, 0x26, 0x26, 0x4c, 0xf8, 0x40, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0xfe, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe7, 0x00, 0x00}, |
{0x00, 0x00, 0xe7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xc1, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xff, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00}, |
{0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe3, 0x33, 0x66, 0x36, 0xe6, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x33, 0x73, 0xb6, 0xf6, 0x36, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdb, 0xdb, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x16, 0x0c, 0x1c, 0x34, 0x62, 0xff, 0x02, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x1a, 0x1c, 0x38, 0x58, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6e, 0x7c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00}, |
{0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00}, |
{0x2a, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00}, |
{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x99, 0x99, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00}, |
{0x33, 0x66, 0x66, 0x66, 0x7e, 0xe7, 0xe7, 0xe7, 0xe7, 0x7e, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00}, |
{0x2a, 0x54, 0x54, 0x54, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00}, |
{0x18, 0x34, 0x30, 0x30, 0x38, 0x35, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00}, |
{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0xfa, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00}, |
{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x5f, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0xfc, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x7e, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x76, 0xdc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xdb, 0xdb, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xdb, 0xdb, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x76, 0xdc, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0xfe, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x06, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0xfb, 0x00, 0x00, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x28, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x44, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x10, 0x7c, 0x28, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x10, 0x28, 0x44, 0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x26, 0x7c, 0xb4, 0x6c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x68, 0x54, 0x54, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x08, 0x10, 0x00, 0x10, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x08, 0x7e, 0x08, 0x10, 0x7e, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x08, 0xfe, 0x08, 0x10, 0xfe, 0x10, 0x20, 0xfe, 0x20, 0x40, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x66, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0xce, 0x7c, 0x10, 0x7c, 0xe6, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x76, 0xdc, 0x80, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x0e, 0x38, 0xe8, 0x38, 0x1e, 0xf0, 0x38, 0x2e, 0x38, 0xe0, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0xe8, 0x38, 0x0e, 0x38, 0xf0, 0x1e, 0x38, 0xe0, 0x38, 0x2e, 0x20, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0xf2, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x9e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x06, 0x0c, 0x38, 0xe8, 0x38, 0x1c, 0x16, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0xd0, 0x70, 0x38, 0x2e, 0x38, 0x60, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0x92, 0xa2, 0xfa, 0xa2, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0x92, 0xfe, 0x92, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xfe, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xaa, 0x92, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x8a, 0x92, 0xa2, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0xd6, 0xba, 0xd6, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xba, 0x82, 0xba, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xba, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0xfe, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x92, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xa8, 0xa8, 0xa8, 0xa8, 0xaf, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc4, 0xc4, 0xff, 0xc8, 0xc8, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xc4, 0xc4, 0xff, 0xc8, 0xff, 0xd0, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xda, 0xdf, 0xda, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xdf, 0xda, 0xdf, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x0c, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x60, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf0, 0xc8, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0b, 0x13, 0x23, 0x43, 0x83, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0xc4, 0xa8, 0x90, 0xa8, 0xc4, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x82, 0x46, 0x2a, 0x12, 0x2a, 0x46, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x3e, 0x60, 0xce, 0xd8, 0xd8, 0xce, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xf8, 0x0c, 0xe6, 0x36, 0x36, 0xe6, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x64, 0xce, 0x64, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x4c, 0xe6, 0x4c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x54, 0xa8, 0x54, 0x2a, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xa8, 0x54, 0x2a, 0x15, 0x2a, 0x54, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00}, |
{0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf2, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xc0, 0x70, 0x9e, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0a, 0x0e, 0x1c, 0xf0, 0x1c, 0x16, 0xf2, 0x1c, 0x26, 0x22, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x88, 0xc8, 0x70, 0x1e, 0x70, 0xd0, 0x9e, 0x70, 0xe0, 0xa0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0xfe, 0xc8, 0xc8, 0xd0, 0xd0, 0xfe, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0xfe, 0x16, 0x16, 0x26, 0x26, 0xfe, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x3d, 0x66, 0xc7, 0xcb, 0xd3, 0xe3, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x42, 0xa5, 0x7e, 0x24, 0x24, 0x7e, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x38, 0x54, 0x8a, 0xf6, 0x82, 0x54, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0xfe, 0xfe, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00}, |
{0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00}, |
{0x00, 0x03, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, |
{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, |
{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x03, 0x00, 0x00}, |
{0x00, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, |
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, |
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0xc0, 0x00, 0x00}, |
{0x00, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, |
{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, |
{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00}, |
{0x00, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, |
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, |
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0x00, 0x00}, |
{0x00, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0}, |
{0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07}, |
{0x00, 0x00, 0xff, 0xc1, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0xc0, 0xc1, 0xff, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x78, 0x78, 0x38, 0x38, 0x18, 0x18, 0x00, 0x00}, |
{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, |
{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}, |
{0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x07, 0x05, 0x05, 0x05, 0x05, 0x25, 0x79, 0xc2, 0x7c, 0x20, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0xd8, 0xd8, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0x70, 0x20, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xf0, 0xc0, 0xe0, 0xc0, 0xc0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0xc0, 0xc0, 0xc0, 0x70, 0x1e, 0x1b, 0x1e, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x98, 0xd8, 0xf8, 0xd8, 0xd8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7c, 0xfe, 0xc6, 0xc6, 0x60, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80}, |
{0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01}, |
{0x81, 0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0x81}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, |
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}, |
{0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc}, |
{0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8}, |
{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0}, |
{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0}, |
{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, |
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, |
{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f}, |
{0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44}, |
{0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa}, |
{0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77}, |
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, |
{0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x82, 0xba, 0xba, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x8a, 0xc6, 0xa2, 0x92, 0x8a, 0xc6, 0xa2, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xa2, 0xc6, 0x8a, 0x92, 0xa2, 0xc6, 0x8a, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x80, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x88, 0x90, 0xa0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x78, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x48, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x98, 0x86, 0x98, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x02, 0x06, 0x0a, 0x12, 0x22, 0x42, 0x22, 0x12, 0x0a, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x78, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x48, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x32, 0xc2, 0x32, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x44, 0x54, 0xba, 0xba, 0x54, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0xbd, 0xbd, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x82, 0x82, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x14, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa5, 0xa5, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x72, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x4e, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, |
{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff}, |
{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff}, |
{0x00, 0x00, 0x30, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff}, |
{0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xff, 0xff}, |
{0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80}, |
{0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0xff, 0xfd, 0xf9, 0xf1, 0xf1, 0xe1, 0xc1, 0x81, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x81, 0x83, 0x87, 0x8f, 0x8f, 0x9f, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x74, 0x74, 0xf2, 0xf2, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x5c, 0x5c, 0x9e, 0x9e, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0xf2, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xf2, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x9e, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0x9e, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x4a, 0x89, 0x89, 0x89, 0xf9, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xf9, 0x89, 0x89, 0x89, 0x4a, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x9f, 0x91, 0x91, 0x91, 0x52, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x52, 0x91, 0x91, 0x91, 0x9f, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x30, 0x7c, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x7c, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0xee, 0x44, 0x54, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x34, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcd, 0xc7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0xa5, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xa5, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x18, 0x30, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x86, 0x8a, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0xee, 0xba, 0xba, 0xee, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x82, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x7c, 0x82, 0xaa, 0x82, 0x44, 0x7c, 0x44, 0x38, 0x00, 0x44, 0xc6, 0x38, 0xc6, 0x44, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x44, 0xee, 0xfe, 0x92, 0xba, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x38, 0x10, 0x10, 0x92, 0xfe, 0x92, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x72, 0xe0, 0xc4, 0xdf, 0xce, 0xca, 0xe0, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x54, 0x28, 0x54, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x5a, 0x99, 0x99, 0x99, 0xbd, 0xff, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x42, 0x81, 0x85, 0xb1, 0xf9, 0xff, 0xdf, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0x81, 0x99, 0xa5, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x28, 0xc6, 0x28, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x78, 0x14, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x14, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x28, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x28, 0x1e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x06, 0x0e, 0x1a, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x03, 0x03, 0x7b, 0xcf, 0xcf, 0xcf, 0x0f, 0x1b, 0x33, 0xff, 0x03, 0x03, 0x03, 0x00, 0x00}, |
{0x00, 0x00, 0x60, 0xf0, 0x60, 0x6e, 0x73, 0x63, 0x63, 0x66, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xd6, 0x54, 0x54, 0x7c, 0x54, 0x54, 0xd6, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x3c, 0xdb, 0xdb, 0xdb, 0xdb, 0x7e, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00}, |
{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x42, 0xa5, 0xa5, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00}, |
{0x00, 0x00, 0xc3, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7e, 0xdb, 0xd8, 0x70, 0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1b, 0x7b, 0xdb, 0xdb, 0x73, 0x03, 0x01, 0x00, 0x00}, |
{0x00, 0x00, 0x94, 0x7c, 0x55, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x06, 0x0b, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x24, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x94, 0x7c, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x04, 0x03, 0x00, 0x00}, |
{0x00, 0x00, 0x1f, 0x07, 0x8f, 0xdb, 0x73, 0x70, 0xd8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x90, 0x50, 0x70, 0x68, 0x48, 0x48, 0x4e, 0x49, 0x09, 0x0e, 0x10, 0x20, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x81, 0x81, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x18, 0x24, 0x3c, 0xe7, 0xa5, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x30, 0x3c, 0x3e, 0x32, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0x7f, 0x6f, 0x63, 0x63, 0x63, 0x63, 0xe3, 0xe7, 0xc7, 0x06, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0xe7, 0xe7, 0xc6, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xde, 0xe6, 0xc4, 0xd8, 0xe0, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x40, 0x40, 0x44, 0x5c, 0x74, 0x44, 0x44, 0x5c, 0x74, 0x44, 0x04, 0x04, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x04, 0x46, 0x5c, 0x74, 0xc4, 0x46, 0x5c, 0x74, 0xc4, 0x40, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3c, 0x6e, 0x66, 0x60, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x3e, 0x6e, 0x66, 0x66, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6e, 0xdb, 0xdb, 0xd8, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x6f, 0xdb, 0xdb, 0xdb, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0xf6, 0x00, 0x00, 0x00, 0x00}, |
{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x88, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x94, 0x80, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x94, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x38, 0x28, 0x70, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x01, 0x02, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00}, |
{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00}, |
{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00}, |
{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xa4, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x70, 0x80, 0x70, 0x80, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf7, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x70, 0x80, 0x70, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x00, 0x2a, 0x02, 0x32, 0x42, 0x32, 0xc6, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x18, 0x10, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x10, 0x00, 0x10}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x10, 0x00, 0x10}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x20, 0x20, 0x20, 0x20, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x10, 0x10, 0x10, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x10, 0x10, 0x10, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x98, 0x60, 0xc2, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x02, 0x92, 0x9c, 0x60, 0x0e, 0x70, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x10, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x04, 0x54, 0x58, 0x20, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x10, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00}, |
{0x0e, 0xf0, 0x02, 0x92, 0x9c, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x18, 0x60, 0x02, 0x92, 0x9c, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x02, 0x12, 0x9c, 0x60, 0x0e, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x10, 0x28, 0x50, 0x28, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x14, 0x28, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x08, 0x10, 0x54, 0x38, 0x54, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x10, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x2a, 0x14, 0x00, 0x21, 0x69, 0xa9, 0x69, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x20, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x30, 0x18, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x08, 0x08, 0x10, 0x10, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x54, 0x58, 0x40, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00}, |
{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x06, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x14, 0x18, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x06, 0x18, 0x60, 0x00, 0x00}, |
{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x02, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x01, 0x3e, 0x40, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x0c, 0x10, 0x0e, 0x10, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00}, |
{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x30, 0x40, 0x38, 0x40, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x50, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x88, 0x80, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00}, |
{0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x0a, 0x00, 0x00, 0x06, 0x09, 0x49, 0x87, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x32, 0x42, 0x32, 0x42, 0x02, 0x86, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3c, 0x4b, 0x4a, 0x44, 0x40, 0x40, 0x40, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x24, 0x28, 0xf3, 0x24, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x24, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00}, |
{0x68, 0x90, 0x02, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x68, 0x90, 0x02, 0x32, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x60, 0x80, 0x72, 0xa2, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x30, 0x40, 0x3a, 0x52, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00}, |
{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00}, |
{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
{0xf1, 0x35, 0x55, 0x8a, 0xe0, 0x06, 0x95, 0xd6, 0xb5, 0x97, 0x00, 0xee, 0x8a, 0xee, 0x28, 0xe8}, |
{0x00, 0x38, 0x7c, 0x7c, 0xc6, 0x92, 0xf2, 0xe6, 0xfe, 0xe6, 0x7c, 0x7c, 0x38, 0x00, 0x00, 0x00}, |
/* Special glyph for unknown character */ |
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00} |
}; |
/* 1 0x01 '^A' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x81, /* 10000001 */ |
0xa5, /* 10100101 */ |
0x81, /* 10000001 */ |
0x81, /* 10000001 */ |
0xbd, /* 10111101 */ |
0x99, /* 10011001 */ |
0x81, /* 10000001 */ |
0x81, /* 10000001 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 2 0x02 '^B' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0xff, /* 11111111 */ |
0xdb, /* 11011011 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xc3, /* 11000011 */ |
0xe7, /* 11100111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 3 0x03 '^C' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x6c, /* 01101100 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0x7c, /* 01111100 */ |
0x38, /* 00111000 */ |
0x10, /* 00010000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 4 0x04 '^D' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x7c, /* 01111100 */ |
0xfe, /* 11111110 */ |
0x7c, /* 01111100 */ |
0x38, /* 00111000 */ |
0x10, /* 00010000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 5 0x05 '^E' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0xe7, /* 11100111 */ |
0xe7, /* 11100111 */ |
0xe7, /* 11100111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 6 0x06 '^F' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x7e, /* 01111110 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 7 0x07 '^G' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 8 0x08 '^H' */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xe7, /* 11100111 */ |
0xc3, /* 11000011 */ |
0xc3, /* 11000011 */ |
0xe7, /* 11100111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
/* 9 0x09 '^I' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x42, /* 01000010 */ |
0x42, /* 01000010 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 10 0x0a '^J' */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xc3, /* 11000011 */ |
0x99, /* 10011001 */ |
0xbd, /* 10111101 */ |
0xbd, /* 10111101 */ |
0x99, /* 10011001 */ |
0xc3, /* 11000011 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
/* 11 0x0b '^K' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1e, /* 00011110 */ |
0x0e, /* 00001110 */ |
0x1a, /* 00011010 */ |
0x32, /* 00110010 */ |
0x78, /* 01111000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 12 0x0c '^L' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 13 0x0d '^M' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3f, /* 00111111 */ |
0x33, /* 00110011 */ |
0x3f, /* 00111111 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x70, /* 01110000 */ |
0xf0, /* 11110000 */ |
0xe0, /* 11100000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 14 0x0e '^N' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7f, /* 01111111 */ |
0x63, /* 01100011 */ |
0x7f, /* 01111111 */ |
0x63, /* 01100011 */ |
0x63, /* 01100011 */ |
0x63, /* 01100011 */ |
0x63, /* 01100011 */ |
0x67, /* 01100111 */ |
0xe7, /* 11100111 */ |
0xe6, /* 11100110 */ |
0xc0, /* 11000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 15 0x0f '^O' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xdb, /* 11011011 */ |
0x3c, /* 00111100 */ |
0xe7, /* 11100111 */ |
0x3c, /* 00111100 */ |
0xdb, /* 11011011 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 16 0x10 '^P' */ |
0x00, /* 00000000 */ |
0x80, /* 10000000 */ |
0xc0, /* 11000000 */ |
0xe0, /* 11100000 */ |
0xf0, /* 11110000 */ |
0xf8, /* 11111000 */ |
0xfe, /* 11111110 */ |
0xf8, /* 11111000 */ |
0xf0, /* 11110000 */ |
0xe0, /* 11100000 */ |
0xc0, /* 11000000 */ |
0x80, /* 10000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 17 0x11 '^Q' */ |
0x00, /* 00000000 */ |
0x02, /* 00000010 */ |
0x06, /* 00000110 */ |
0x0e, /* 00001110 */ |
0x1e, /* 00011110 */ |
0x3e, /* 00111110 */ |
0xfe, /* 11111110 */ |
0x3e, /* 00111110 */ |
0x1e, /* 00011110 */ |
0x0e, /* 00001110 */ |
0x06, /* 00000110 */ |
0x02, /* 00000010 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 18 0x12 '^R' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 19 0x13 '^S' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 20 0x14 '^T' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7f, /* 01111111 */ |
0xdb, /* 11011011 */ |
0xdb, /* 11011011 */ |
0xdb, /* 11011011 */ |
0x7b, /* 01111011 */ |
0x1b, /* 00011011 */ |
0x1b, /* 00011011 */ |
0x1b, /* 00011011 */ |
0x1b, /* 00011011 */ |
0x1b, /* 00011011 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 21 0x15 '^U' */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0x60, /* 01100000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x0c, /* 00001100 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 22 0x16 '^V' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 23 0x17 '^W' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 24 0x18 '^X' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 25 0x19 '^Y' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 26 0x1a '^Z' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0xfe, /* 11111110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 27 0x1b '^[' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xfe, /* 11111110 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 28 0x1c '^\' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 29 0x1d '^]' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x28, /* 00101000 */ |
0x6c, /* 01101100 */ |
0xfe, /* 11111110 */ |
0x6c, /* 01101100 */ |
0x28, /* 00101000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 30 0x1e '^^' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x38, /* 00111000 */ |
0x7c, /* 01111100 */ |
0x7c, /* 01111100 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 31 0x1f '^_' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0x7c, /* 01111100 */ |
0x7c, /* 01111100 */ |
0x38, /* 00111000 */ |
0x38, /* 00111000 */ |
0x10, /* 00010000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 32 0x20 ' ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 33 0x21 '!' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 34 0x22 '"' */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x24, /* 00100100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 35 0x23 '#' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0xfe, /* 11111110 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0xfe, /* 11111110 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 36 0x24 '$' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc2, /* 11000010 */ |
0xc0, /* 11000000 */ |
0x7c, /* 01111100 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x86, /* 10000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 37 0x25 '%' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc2, /* 11000010 */ |
0xc6, /* 11000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc6, /* 11000110 */ |
0x86, /* 10000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 38 0x26 '&' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 39 0x27 ''' */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 40 0x28 '(' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 41 0x29 ')' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 42 0x2a '*' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0xff, /* 11111111 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 43 0x2b '+' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 44 0x2c ',' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 45 0x2d '-' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 46 0x2e '.' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 47 0x2f '/' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x02, /* 00000010 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0x80, /* 10000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 48 0x30 '0' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 49 0x31 '1' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x38, /* 00111000 */ |
0x78, /* 01111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 50 0x32 '2' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 51 0x33 '3' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x3c, /* 00111100 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 52 0x34 '4' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x0c, /* 00001100 */ |
0x1c, /* 00011100 */ |
0x3c, /* 00111100 */ |
0x6c, /* 01101100 */ |
0xcc, /* 11001100 */ |
0xfe, /* 11111110 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x1e, /* 00011110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 53 0x35 '5' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xfc, /* 11111100 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 54 0x36 '6' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xfc, /* 11111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 55 0x37 '7' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 56 0x38 '8' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 57 0x39 '9' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7e, /* 01111110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 58 0x3a ':' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 59 0x3b ';' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 60 0x3c '<' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x06, /* 00000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 61 0x3d '=' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 62 0x3e '>' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 63 0x3f '?' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 64 0x40 '@' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xde, /* 11011110 */ |
0xde, /* 11011110 */ |
0xde, /* 11011110 */ |
0xdc, /* 11011100 */ |
0xc0, /* 11000000 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 65 0x41 'A' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 66 0x42 'B' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfc, /* 11111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0xfc, /* 11111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 67 0x43 'C' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0xc2, /* 11000010 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc2, /* 11000010 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 68 0x44 'D' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xf8, /* 11111000 */ |
0x6c, /* 01101100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x6c, /* 01101100 */ |
0xf8, /* 11111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 69 0x45 'E' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x66, /* 01100110 */ |
0x62, /* 01100010 */ |
0x68, /* 01101000 */ |
0x78, /* 01111000 */ |
0x68, /* 01101000 */ |
0x60, /* 01100000 */ |
0x62, /* 01100010 */ |
0x66, /* 01100110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 70 0x46 'F' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x66, /* 01100110 */ |
0x62, /* 01100010 */ |
0x68, /* 01101000 */ |
0x78, /* 01111000 */ |
0x68, /* 01101000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xf0, /* 11110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 71 0x47 'G' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0xc2, /* 11000010 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xde, /* 11011110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x66, /* 01100110 */ |
0x3a, /* 00111010 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 72 0x48 'H' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 73 0x49 'I' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 74 0x4a 'J' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1e, /* 00011110 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 75 0x4b 'K' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xe6, /* 11100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x6c, /* 01101100 */ |
0x78, /* 01111000 */ |
0x78, /* 01111000 */ |
0x6c, /* 01101100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0xe6, /* 11100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 76 0x4c 'L' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xf0, /* 11110000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x62, /* 01100010 */ |
0x66, /* 01100110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 77 0x4d 'M' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xee, /* 11101110 */ |
0xfe, /* 11111110 */ |
0xfe, /* 11111110 */ |
0xd6, /* 11010110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 78 0x4e 'N' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xe6, /* 11100110 */ |
0xf6, /* 11110110 */ |
0xfe, /* 11111110 */ |
0xde, /* 11011110 */ |
0xce, /* 11001110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 79 0x4f 'O' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 80 0x50 'P' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfc, /* 11111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xf0, /* 11110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 81 0x51 'Q' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xd6, /* 11010110 */ |
0xde, /* 11011110 */ |
0x7c, /* 01111100 */ |
0x0c, /* 00001100 */ |
0x0e, /* 00001110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 82 0x52 'R' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfc, /* 11111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x6c, /* 01101100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0xe6, /* 11100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 83 0x53 'S' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x60, /* 01100000 */ |
0x38, /* 00111000 */ |
0x0c, /* 00001100 */ |
0x06, /* 00000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 84 0x54 'T' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x5a, /* 01011010 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 85 0x55 'U' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 86 0x56 'V' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x10, /* 00010000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 87 0x57 'W' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xfe, /* 11111110 */ |
0xee, /* 11101110 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 88 0x58 'X' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x7c, /* 01111100 */ |
0x38, /* 00111000 */ |
0x38, /* 00111000 */ |
0x7c, /* 01111100 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 89 0x59 'Y' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 90 0x5a 'Z' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0x86, /* 10000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc2, /* 11000010 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 91 0x5b '[' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 92 0x5c '\' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x80, /* 10000000 */ |
0xc0, /* 11000000 */ |
0xe0, /* 11100000 */ |
0x70, /* 01110000 */ |
0x38, /* 00111000 */ |
0x1c, /* 00011100 */ |
0x0e, /* 00001110 */ |
0x06, /* 00000110 */ |
0x02, /* 00000010 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 93 0x5d ']' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 94 0x5e '^' */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 95 0x5f '_' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 96 0x60 '`' */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 97 0x61 'a' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 98 0x62 'b' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xe0, /* 11100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x78, /* 01111000 */ |
0x6c, /* 01101100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 99 0x63 'c' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 100 0x64 'd' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1c, /* 00011100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x3c, /* 00111100 */ |
0x6c, /* 01101100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 101 0x65 'e' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 102 0x66 'f' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1c, /* 00011100 */ |
0x36, /* 00110110 */ |
0x32, /* 00110010 */ |
0x30, /* 00110000 */ |
0x78, /* 01111000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 103 0x67 'g' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x7c, /* 01111100 */ |
0x0c, /* 00001100 */ |
0xcc, /* 11001100 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
/* 104 0x68 'h' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xe0, /* 11100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x6c, /* 01101100 */ |
0x76, /* 01110110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0xe6, /* 11100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 105 0x69 'i' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 106 0x6a 'j' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x00, /* 00000000 */ |
0x0e, /* 00001110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
/* 107 0x6b 'k' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xe0, /* 11100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x66, /* 01100110 */ |
0x6c, /* 01101100 */ |
0x78, /* 01111000 */ |
0x78, /* 01111000 */ |
0x6c, /* 01101100 */ |
0x66, /* 01100110 */ |
0xe6, /* 11100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 108 0x6c 'l' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 109 0x6d 'm' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xec, /* 11101100 */ |
0xfe, /* 11111110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 110 0x6e 'n' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xdc, /* 11011100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 111 0x6f 'o' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 112 0x70 'p' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xdc, /* 11011100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xf0, /* 11110000 */ |
0x00, /* 00000000 */ |
/* 113 0x71 'q' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x7c, /* 01111100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x1e, /* 00011110 */ |
0x00, /* 00000000 */ |
/* 114 0x72 'r' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xdc, /* 11011100 */ |
0x76, /* 01110110 */ |
0x66, /* 01100110 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xf0, /* 11110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 115 0x73 's' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0x60, /* 01100000 */ |
0x38, /* 00111000 */ |
0x0c, /* 00001100 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 116 0x74 't' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0xfc, /* 11111100 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x36, /* 00110110 */ |
0x1c, /* 00011100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 117 0x75 'u' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 118 0x76 'v' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 119 0x77 'w' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xd6, /* 11010110 */ |
0xfe, /* 11111110 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 120 0x78 'x' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x38, /* 00111000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 121 0x79 'y' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7e, /* 01111110 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0xf8, /* 11111000 */ |
0x00, /* 00000000 */ |
/* 122 0x7a 'z' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xcc, /* 11001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 123 0x7b '{' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x0e, /* 00001110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x70, /* 01110000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x0e, /* 00001110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 124 0x7c '|' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 125 0x7d '}' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x70, /* 01110000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x0e, /* 00001110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 126 0x7e '~' */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 127 0x7f '' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 128 0x80 '€' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0xc2, /* 11000010 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc2, /* 11000010 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 129 0x81 '' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 130 0x82 '‚' */ |
0x00, /* 00000000 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 131 0x83 'ƒ' */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 132 0x84 '„' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 133 0x85 '…' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 134 0x86 '†' */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 135 0x87 '‡' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x18, /* 00011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 136 0x88 'ˆ' */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 137 0x89 '‰' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 138 0x8a 'Š' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 139 0x8b '‹' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 140 0x8c 'Œ' */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 141 0x8d '' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 142 0x8e 'Ž' */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 143 0x8f '' */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 144 0x90 '' */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x66, /* 01100110 */ |
0x62, /* 01100010 */ |
0x68, /* 01101000 */ |
0x78, /* 01111000 */ |
0x68, /* 01101000 */ |
0x62, /* 01100010 */ |
0x66, /* 01100110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 145 0x91 '‘' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xec, /* 11101100 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x7e, /* 01111110 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0x6e, /* 01101110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 146 0x92 '’' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3e, /* 00111110 */ |
0x6c, /* 01101100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xfe, /* 11111110 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xce, /* 11001110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 147 0x93 '“' */ |
0x00, /* 00000000 */ |
0x10, /* 00010000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 148 0x94 '”' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 149 0x95 '•' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 150 0x96 '–' */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x78, /* 01111000 */ |
0xcc, /* 11001100 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 151 0x97 '—' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 152 0x98 '˜' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7e, /* 01111110 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x78, /* 01111000 */ |
0x00, /* 00000000 */ |
/* 153 0x99 '™' */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 154 0x9a 'š' */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 155 0x9b '›' */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 156 0x9c 'œ' */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x64, /* 01100100 */ |
0x60, /* 01100000 */ |
0xf0, /* 11110000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xe6, /* 11100110 */ |
0xfc, /* 11111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 157 0x9d '' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 158 0x9e 'ž' */ |
0x00, /* 00000000 */ |
0xf8, /* 11111000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xf8, /* 11111000 */ |
0xc4, /* 11000100 */ |
0xcc, /* 11001100 */ |
0xde, /* 11011110 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 159 0x9f 'Ÿ' */ |
0x00, /* 00000000 */ |
0x0e, /* 00001110 */ |
0x1b, /* 00011011 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xd8, /* 11011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 160 0xa0 ' ' */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0x0c, /* 00001100 */ |
0x7c, /* 01111100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 161 0xa1 '¡' */ |
0x00, /* 00000000 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 162 0xa2 '¢' */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 163 0xa3 '£' */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x00, /* 00000000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 164 0xa4 '¤' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x00, /* 00000000 */ |
0xdc, /* 11011100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 165 0xa5 '¥' */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x00, /* 00000000 */ |
0xc6, /* 11000110 */ |
0xe6, /* 11100110 */ |
0xf6, /* 11110110 */ |
0xfe, /* 11111110 */ |
0xde, /* 11011110 */ |
0xce, /* 11001110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 166 0xa6 '¦' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x3e, /* 00111110 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 167 0xa7 '§' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 168 0xa8 '¨' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x7c, /* 01111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 169 0xa9 '©' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 170 0xaa 'ª' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 171 0xab '«' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0xe0, /* 11100000 */ |
0x62, /* 01100010 */ |
0x66, /* 01100110 */ |
0x6c, /* 01101100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xdc, /* 11011100 */ |
0x86, /* 10000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x3e, /* 00111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 172 0xac '¬' */ |
0x00, /* 00000000 */ |
0x60, /* 01100000 */ |
0xe0, /* 11100000 */ |
0x62, /* 01100010 */ |
0x66, /* 01100110 */ |
0x6c, /* 01101100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x66, /* 01100110 */ |
0xce, /* 11001110 */ |
0x9a, /* 10011010 */ |
0x3f, /* 00111111 */ |
0x06, /* 00000110 */ |
0x06, /* 00000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 173 0xad '' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 174 0xae '®' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x36, /* 00110110 */ |
0x6c, /* 01101100 */ |
0xd8, /* 11011000 */ |
0x6c, /* 01101100 */ |
0x36, /* 00110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 175 0xaf '¯' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xd8, /* 11011000 */ |
0x6c, /* 01101100 */ |
0x36, /* 00110110 */ |
0x6c, /* 01101100 */ |
0xd8, /* 11011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 176 0xb0 '°' */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
0x11, /* 00010001 */ |
0x44, /* 01000100 */ |
/* 177 0xb1 '±' */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
0x55, /* 01010101 */ |
0xaa, /* 10101010 */ |
/* 178 0xb2 '²' */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
0xdd, /* 11011101 */ |
0x77, /* 01110111 */ |
/* 179 0xb3 '³' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 180 0xb4 '´' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 181 0xb5 'µ' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 182 0xb6 '¶' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xf6, /* 11110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 183 0xb7 '·' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 184 0xb8 '¸' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 185 0xb9 '¹' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xf6, /* 11110110 */ |
0x06, /* 00000110 */ |
0xf6, /* 11110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 186 0xba 'º' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 187 0xbb '»' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x06, /* 00000110 */ |
0xf6, /* 11110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 188 0xbc '¼' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xf6, /* 11110110 */ |
0x06, /* 00000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 189 0xbd '½' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 190 0xbe '¾' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 191 0xbf '¿' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xf8, /* 11111000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 192 0xc0 'À' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 193 0xc1 'Á' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 194 0xc2 'Â' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 195 0xc3 'Ã' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 196 0xc4 'Ä' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 197 0xc5 'Å' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xff, /* 11111111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 198 0xc6 'Æ' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 199 0xc7 'Ç' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x37, /* 00110111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 200 0xc8 'È' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x37, /* 00110111 */ |
0x30, /* 00110000 */ |
0x3f, /* 00111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 201 0xc9 'É' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3f, /* 00111111 */ |
0x30, /* 00110000 */ |
0x37, /* 00110111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 202 0xca 'Ê' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xf7, /* 11110111 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 203 0xcb 'Ë' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0xf7, /* 11110111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 204 0xcc 'Ì' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x37, /* 00110111 */ |
0x30, /* 00110000 */ |
0x37, /* 00110111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 205 0xcd 'Í' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 206 0xce 'Î' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xf7, /* 11110111 */ |
0x00, /* 00000000 */ |
0xf7, /* 11110111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 207 0xcf 'Ï' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 208 0xd0 'Ð' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 209 0xd1 'Ñ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 210 0xd2 'Ò' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 211 0xd3 'Ó' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x3f, /* 00111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 212 0xd4 'Ô' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 213 0xd5 'Õ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 214 0xd6 'Ö' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x3f, /* 00111111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 215 0xd7 '×' */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0xff, /* 11111111 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
/* 216 0xd8 'Ø' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xff, /* 11111111 */ |
0x18, /* 00011000 */ |
0xff, /* 11111111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 217 0xd9 'Ù' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xf8, /* 11111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 218 0xda 'Ú' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1f, /* 00011111 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 219 0xdb 'Û' */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
/* 220 0xdc 'Ü' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
/* 221 0xdd 'Ý' */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
0xf0, /* 11110000 */ |
/* 222 0xde 'Þ' */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
0x0f, /* 00001111 */ |
/* 223 0xdf 'ß' */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0xff, /* 11111111 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 224 0xe0 'à' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xdc, /* 11011100 */ |
0x76, /* 01110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 225 0xe1 'á' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x78, /* 01111000 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xcc, /* 11001100 */ |
0xd8, /* 11011000 */ |
0xcc, /* 11001100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xcc, /* 11001100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 226 0xe2 'â' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0xc0, /* 11000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 227 0xe3 'ã' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 228 0xe4 'ä' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 229 0xe5 'å' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 230 0xe6 'æ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x7c, /* 01111100 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0x00, /* 00000000 */ |
/* 231 0xe7 'ç' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 232 0xe8 'è' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 233 0xe9 'é' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xfe, /* 11111110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 234 0xea 'ê' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0xee, /* 11101110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 235 0xeb 'ë' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1e, /* 00011110 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x3e, /* 00111110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x66, /* 01100110 */ |
0x3c, /* 00111100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 236 0xec 'ì' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0xdb, /* 11011011 */ |
0xdb, /* 11011011 */ |
0xdb, /* 11011011 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 237 0xed 'í' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x03, /* 00000011 */ |
0x06, /* 00000110 */ |
0x7e, /* 01111110 */ |
0xdb, /* 11011011 */ |
0xdb, /* 11011011 */ |
0xf3, /* 11110011 */ |
0x7e, /* 01111110 */ |
0x60, /* 01100000 */ |
0xc0, /* 11000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 238 0xee 'î' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x1c, /* 00011100 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x7c, /* 01111100 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x1c, /* 00011100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 239 0xef 'ï' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7c, /* 01111100 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0xc6, /* 11000110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 240 0xf0 'ð' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0xfe, /* 11111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 241 0xf1 'ñ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x7e, /* 01111110 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 242 0xf2 'ò' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x06, /* 00000110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 243 0xf3 'ó' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x30, /* 00110000 */ |
0x60, /* 01100000 */ |
0x30, /* 00110000 */ |
0x18, /* 00011000 */ |
0x0c, /* 00001100 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 244 0xf4 'ô' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x0e, /* 00001110 */ |
0x1b, /* 00011011 */ |
0x1b, /* 00011011 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
/* 245 0xf5 'õ' */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0xd8, /* 11011000 */ |
0x70, /* 01110000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 246 0xf6 'ö' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 247 0xf7 '÷' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x00, /* 00000000 */ |
0x76, /* 01110110 */ |
0xdc, /* 11011100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 248 0xf8 'ø' */ |
0x00, /* 00000000 */ |
0x38, /* 00111000 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x38, /* 00111000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 249 0xf9 'ù' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 250 0xfa 'ú' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x18, /* 00011000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 251 0xfb 'û' */ |
0x00, /* 00000000 */ |
0x0f, /* 00001111 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0x0c, /* 00001100 */ |
0xec, /* 11101100 */ |
0x6c, /* 01101100 */ |
0x6c, /* 01101100 */ |
0x3c, /* 00111100 */ |
0x1c, /* 00011100 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 252 0xfc 'ü' */ |
0x00, /* 00000000 */ |
0x6c, /* 01101100 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x36, /* 00110110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 253 0xfd 'ý' */ |
0x00, /* 00000000 */ |
0x3c, /* 00111100 */ |
0x66, /* 01100110 */ |
0x0c, /* 00001100 */ |
0x18, /* 00011000 */ |
0x32, /* 00110010 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 254 0xfe 'þ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x7e, /* 01111110 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
/* 255 0xff 'ÿ' */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
0x00, /* 00000000 */ |
}; |
/** @} |
*/ |
/branches/arm/uspace/srv/fb/font-8x16.h |
---|
26,12 → 26,25 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifndef FB_FONT_8X16_H_ |
#define FB_FONT_8X16_H_ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#define FONT_GLIPHS 256 |
#define FONT_SCANLINES 16 |
#ifndef FONT_8X16_H_ |
#define FONT_8X16_H_ |
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES]; |
#define FONT_GLYPHS 2899 |
#define FONT_WIDTH 8 |
#define FONT_SCANLINES 16 |
#include <sys/types.h> |
extern uint16_t fb_font_glyph(const wchar_t ch); |
extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES]; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/fb/msim.c |
---|
36,29 → 36,17 |
*/ |
#include <async.h> |
#include <ipc/fb.h> |
#include <ipc/ipc.h> |
#include <libc.h> |
#include <errno.h> |
#include <string.h> |
#include <libc.h> |
#include <stdio.h> |
#include <ipc/fb.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <align.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "msim.h" |
#define WIDTH 80 |
#define HEIGHT 25 |
#define HEIGHT 24 |
#define MAX_CONTROL 20 |
/* Allow only 1 connection */ |
static int client_connected = 0; |
static char *virt_addr; |
static void msim_putc(const char c) |
66,159 → 54,17 |
*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; |
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 - 25 lines */ |
msim_clrscr(); |
msim_goto(0, 0); |
msim_puts("\033[0;25r"); |
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)) |
msim_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
msim_putc(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
msim_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: |
msim_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
msim_set_style(0); |
else |
msim_set_style(7); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > HEIGHT) || (i < -HEIGHT)) { |
retval = EINVAL; |
break; |
} |
msim_scroll(i); |
msim_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
msim_cursor_enable(); |
else |
msim_cursor_disable(); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
int msim_init(void) |
{ |
void *phys_addr = (void *) sysinfo_value("fb.address.physical"); |
virt_addr = (char *) as_get_mappable_page(1); |
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE); |
if (physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
async_set_client_connection(msim_client_connection); |
serial_console_init(msim_putc, WIDTH, HEIGHT); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/branches/arm/uspace/srv/fb/ski.c |
---|
0,0 → 1,84 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup msimfb MSIM text console |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <libc.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "ski.h" |
#define SKI_PUTCHAR 31 |
#define WIDTH 80 |
#define HEIGHT 24 |
/** Display character on ski debug console |
* |
* Use SSC (Simulator System Call) to |
* display character on debug console. |
* |
* @param ch Character to be printed. |
*/ |
static void ski_putc(const char ch) |
{ |
asm volatile ( |
"mov r15 = %0\n" |
"mov r32 = %1\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: "i" (SKI_PUTCHAR), "r" (ch) |
: "r15", "in0", "r8" |
); |
if (ch == '\n') |
ski_putc('\r'); |
} |
int ski_init(void) |
{ |
serial_console_init(ski_putc, WIDTH, HEIGHT); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fb/sgcn.c |
---|
0,0 → 1,142 |
/* |
* 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 <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; |
/** |
* 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; |
} |
/** |
* Initializes the SGCN serial driver. |
*/ |
int sgcn_init(void) |
{ |
sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size")); |
if (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) != 0) |
return -1; |
serial_console_init(sgcn_putc, WIDTH, HEIGHT); |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fb/ski.h |
---|
0,0 → 1,46 |
/* |
* 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. |
*/ |
/** @addtogroup skifb |
* @brief HelenOS ski text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SKI_H_ |
#define FB_SKI_H_ |
extern int ski_init(void); |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/fb/main.c |
---|
38,6 → 38,8 |
#include "fb.h" |
#include "ega.h" |
#include "msim.h" |
#include "ski.h" |
#include "sgcn.h" |
#include "main.h" |
#define NAME "fb" |
45,7 → 47,7 |
void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area) |
{ |
void *dest; |
dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest) == 0) { |
if (*area) |
60,12 → 62,12 |
ipcarg_t phonead; |
bool initialized = false; |
#ifdef FB_ENABLED |
if (sysinfo_value("fb.kind") == 1) { |
if (fb_init() == 0) |
initialized = true; |
} |
} |
#endif |
#ifdef EGA_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) { |
79,15 → 81,28 |
initialized = true; |
} |
#endif |
#ifdef SGCN_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 4)) { |
if (sgcn_init() == 0) |
initialized = true; |
} |
#endif |
#ifdef SKI_ENABLED |
if ((!initialized) && (sysinfo_value("fb") != true)) { |
if (ski_init() == 0) |
initialized = true; |
} |
#endif |
if (!initialized) |
return -1; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/branches/arm/uspace/srv/fb/fb.h |
---|
29,7 → 29,7 |
/** @addtogroup fb |
* @ingroup fbs |
* @{ |
*/ |
*/ |
/** @file |
*/ |
36,8 → 36,10 |
#ifndef FB_FB_H_ |
#define FB_FB_H_ |
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, int); |
#include <stdint.h> |
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t); |
extern int fb_init(void); |
#endif |
/branches/arm/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/arm/uspace/srv/bd/ata_bd/ata_bd.c |
---|
0,0 → 1,441 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup bd |
* @{ |
*/ |
/** |
* @file |
* @brief ATA disk driver |
* |
* This driver currently works only with CHS addressing and uses PIO. |
* Currently based on the (now obsolete) ANSI X3.221-1994 (ATA-1) standard. |
* At this point only reading is possible, not writing. |
* |
* The driver services a single controller which can have up to two disks |
* attached. |
*/ |
#include <stdio.h> |
#include <libarch/ddi.h> |
#include <ddi.h> |
#include <ipc/ipc.h> |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#include "ata_bd.h" |
#define NAME "ata_bd" |
static const size_t block_size = 512; |
static size_t comm_size; |
static uintptr_t cmd_physical = 0x1f0; |
static uintptr_t ctl_physical = 0x170; |
static ata_cmd_t *cmd; |
static ata_ctl_t *ctl; |
/** Per-disk state. */ |
static disk_t disk[MAX_DISKS]; |
static int ata_bd_init(void); |
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf); |
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
void *buf); |
static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
const void *buf); |
static int drive_identify(int drive_id, disk_t *d); |
int main(int argc, char **argv) |
{ |
uint8_t status; |
char name[16]; |
int i, rc; |
int n_disks; |
printf(NAME ": ATA disk driver\n"); |
printf("I/O address 0x%x\n", cmd_physical); |
if (ata_bd_init() != EOK) |
return -1; |
/* Put drives to reset, disable interrupts. */ |
printf("Reset drives... "); |
fflush(stdout); |
pio_write_8(&ctl->device_control, DCR_SRST); |
/* FIXME: Find out how to do this properly. */ |
async_usleep(100); |
pio_write_8(&ctl->device_control, 0); |
do { |
status = pio_read_8(&cmd->status); |
} while ((status & SR_BSY) != 0); |
printf("Done\n"); |
(void) drive_identify(0, &disk[0]); |
(void) drive_identify(1, &disk[1]); |
n_disks = 0; |
for (i = 0; i < MAX_DISKS; i++) { |
/* Skip unattached drives. */ |
if (disk[i].present == false) |
continue; |
snprintf(name, 16, "disk%d", i); |
rc = devmap_device_register(name, &disk[i].dev_handle); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s.\n", |
name); |
return rc; |
} |
++n_disks; |
} |
if (n_disks == 0) { |
printf("No disks detected.\n"); |
return -1; |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
static int drive_identify(int disk_id, disk_t *d) |
{ |
uint16_t data; |
uint8_t status; |
size_t i; |
printf("Identify drive %d... ", disk_id); |
fflush(stdout); |
pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0)); |
async_usleep(100); |
pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); |
status = pio_read_8(&cmd->status); |
d->present = false; |
/* |
* Detect if drive is present. This is Qemu only! Need to |
* do the right thing to work with real drives. |
*/ |
if ((status & SR_DRDY) == 0) { |
printf("None attached.\n"); |
return ENOENT; |
} |
for (i = 0; i < block_size / 2; i++) { |
do { |
status = pio_read_8(&cmd->status); |
} while ((status & SR_DRDY) == 0); |
data = pio_read_16(&cmd->data_port); |
switch (i) { |
case 1: d->cylinders = data; break; |
case 3: d->heads = data; break; |
case 6: d->sectors = data; break; |
} |
} |
d->blocks = d->cylinders * d->heads * d->sectors; |
printf("Geometry: %u cylinders, %u heads, %u sectors\n", |
d->cylinders, d->heads, d->sectors); |
d->present = true; |
fibril_mutex_initialize(&d->lock); |
return EOK; |
} |
static int ata_bd_init(void) |
{ |
void *vaddr; |
int rc; |
rc = devmap_driver_register(NAME, ata_bd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver.\n"); |
return rc; |
} |
rc = pio_enable((void *) cmd_physical, sizeof(ata_cmd_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
cmd = vaddr; |
rc = pio_enable((void *) ctl_physical, sizeof(ata_ctl_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
ctl = vaddr; |
return EOK; |
} |
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
void *fs_va = NULL; |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t method; |
dev_handle_t dh; |
int flags; |
int retval; |
off_t idx; |
size_t size; |
int disk_id, i; |
/* Get the device handle. */ |
dh = IPC_GET_ARG1(*icall); |
/* Determine which disk device is the client connecting to. */ |
disk_id = -1; |
for (i = 0; i < MAX_DISKS; i++) |
if (disk[i].dev_handle == dh) |
disk_id = i; |
if (disk_id < 0 || disk[disk_id].present == false) { |
ipc_answer_0(iid, EINVAL); |
return; |
} |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
if (!ipc_share_out_receive(&callid, &comm_size, &flags)) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
fs_va = as_get_mappable_page(comm_size); |
if (fs_va == NULL) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
(void) ipc_share_out_finalize(callid, fs_va); |
while (1) { |
callid = async_get_call(&call); |
method = IPC_GET_METHOD(call); |
switch (method) { |
case IPC_M_PHONE_HUNGUP: |
/* The other side has hung up. */ |
ipc_answer_0(callid, EOK); |
return; |
case BD_READ_BLOCK: |
case BD_WRITE_BLOCK: |
idx = IPC_GET_ARG1(call); |
size = IPC_GET_ARG2(call); |
if (size > comm_size) { |
retval = EINVAL; |
break; |
} |
retval = ata_bd_rdwr(disk_id, method, idx, |
size, fs_va); |
break; |
default: |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size, |
void *buf) |
{ |
int rc; |
size_t now; |
while (size > 0) { |
now = size < block_size ? size : block_size; |
if (now != block_size) |
return EINVAL; |
if (method == BD_READ_BLOCK) |
rc = ata_bd_read_block(disk_id, blk_idx, 1, buf); |
else |
rc = ata_bd_write_block(disk_id, blk_idx, 1, buf); |
if (rc != EOK) |
return rc; |
buf += block_size; |
blk_idx++; |
if (size > block_size) |
size -= block_size; |
else |
size = 0; |
} |
return EOK; |
} |
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
void *buf) |
{ |
size_t i; |
uint16_t data; |
uint8_t status; |
uint64_t c, h, s; |
uint64_t idx; |
uint8_t drv_head; |
disk_t *d; |
d = &disk[disk_id]; |
/* Check device bounds. */ |
if (blk_idx >= d->blocks) |
return EINVAL; |
/* Compute CHS. */ |
c = blk_idx / (d->heads * d->sectors); |
idx = blk_idx % (d->heads * d->sectors); |
h = idx / d->sectors; |
s = 1 + (idx % d->sectors); |
/* New value for Drive/Head register */ |
drv_head = |
((disk_id != 0) ? DHR_DRV : 0) | |
(h & 0x0f); |
fibril_mutex_lock(&d->lock); |
/* Program a Read Sectors operation. */ |
pio_write_8(&cmd->drive_head, drv_head); |
pio_write_8(&cmd->sector_count, 1); |
pio_write_8(&cmd->sector_number, s); |
pio_write_8(&cmd->cylinder_low, c & 0xff); |
pio_write_8(&cmd->cylinder_high, c >> 16); |
pio_write_8(&cmd->command, CMD_READ_SECTORS); |
/* Read data from the disk buffer. */ |
for (i = 0; i < block_size / 2; i++) { |
do { |
status = pio_read_8(&cmd->status); |
} while ((status & SR_DRDY) == 0); |
data = pio_read_16(&cmd->data_port); |
((uint16_t *) buf)[i] = data; |
} |
fibril_mutex_unlock(&d->lock); |
return EOK; |
} |
static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
const void *buf) |
{ |
size_t i; |
uint8_t status; |
uint64_t c, h, s; |
uint64_t idx; |
uint8_t drv_head; |
disk_t *d; |
d = &disk[disk_id]; |
/* Check device bounds. */ |
if (blk_idx >= d->blocks) |
return EINVAL; |
/* Compute CHS. */ |
c = blk_idx / (d->heads * d->sectors); |
idx = blk_idx % (d->heads * d->sectors); |
h = idx / d->sectors; |
s = 1 + (idx % d->sectors); |
/* New value for Drive/Head register */ |
drv_head = |
((disk_id != 0) ? DHR_DRV : 0) | |
(h & 0x0f); |
fibril_mutex_lock(&d->lock); |
/* Program a Read Sectors operation. */ |
pio_write_8(&cmd->drive_head, drv_head); |
pio_write_8(&cmd->sector_count, 1); |
pio_write_8(&cmd->sector_number, s); |
pio_write_8(&cmd->cylinder_low, c & 0xff); |
pio_write_8(&cmd->cylinder_high, c >> 16); |
pio_write_8(&cmd->command, CMD_WRITE_SECTORS); |
/* Write data to the disk buffer. */ |
for (i = 0; i < block_size / 2; i++) { |
do { |
status = pio_read_8(&cmd->status); |
} while ((status & SR_DRDY) == 0); |
pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); |
} |
fibril_mutex_unlock(&d->lock); |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/bd/ata_bd/ata_bd.h |
---|
0,0 → 1,151 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup bd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef __ATA_BD_H__ |
#define __ATA_BD_H__ |
#include <sys/types.h> |
#include <fibril_sync.h> |
enum { |
CTL_READ_START = 0, |
CTL_WRITE_START = 1, |
}; |
enum { |
STATUS_FAILURE = 0 |
}; |
enum { |
MAX_DISKS = 2 |
}; |
/** ATA Command Register Block. */ |
typedef union { |
/* Read/Write */ |
struct { |
uint16_t data_port; |
uint8_t sector_count; |
uint8_t sector_number; |
uint8_t cylinder_low; |
uint8_t cylinder_high; |
uint8_t drive_head; |
uint8_t pad_rw0; |
}; |
/* Read Only */ |
struct { |
uint8_t pad_ro0; |
uint8_t error; |
uint8_t pad_ro1[5]; |
uint8_t status; |
}; |
/* Write Only */ |
struct { |
uint8_t pad_wo0; |
uint8_t features; |
uint8_t pad_wo1[5]; |
uint8_t command; |
}; |
} ata_cmd_t; |
typedef union { |
/* Read */ |
struct { |
uint8_t pad0[6]; |
uint8_t alt_status; |
uint8_t drive_address; |
}; |
/* Write */ |
struct { |
uint8_t pad1[6]; |
uint8_t device_control; |
uint8_t pad2; |
}; |
} ata_ctl_t; |
enum devctl_bits { |
DCR_SRST = 0x04, /**< Software Reset */ |
DCR_nIEN = 0x02 /**< Interrupt Enable (negated) */ |
}; |
enum status_bits { |
SR_BSY = 0x80, /**< Busy */ |
SR_DRDY = 0x40, /**< Drive Ready */ |
SR_DWF = 0x20, /**< Drive Write Fault */ |
SR_DSC = 0x10, /**< Drive Seek Complete */ |
SR_DRQ = 0x08, /**< Data Request */ |
SR_CORR = 0x04, /**< Corrected Data */ |
SR_IDX = 0x02, /**< Index */ |
SR_ERR = 0x01 /**< Error */ |
}; |
enum drive_head_bits { |
DHR_DRV = 0x10 |
}; |
enum error_bits { |
ER_BBK = 0x80, /**< Bad Block Detected */ |
ER_UNC = 0x40, /**< Uncorrectable Data Error */ |
ER_MC = 0x20, /**< Media Changed */ |
ER_IDNF = 0x10, /**< ID Not Found */ |
ER_MCR = 0x08, /**< Media Change Request */ |
ER_ABRT = 0x04, /**< Aborted Command */ |
ER_TK0NF = 0x02, /**< Track 0 Not Found */ |
ER_AMNF = 0x01 /**< Address Mark Not Found */ |
}; |
enum ata_command { |
CMD_IDENTIFY_DRIVE = 0xEC, |
CMD_READ_SECTORS = 0x20, |
CMD_WRITE_SECTORS = 0x30 |
}; |
typedef struct { |
bool present; |
unsigned heads; |
unsigned cylinders; |
unsigned sectors; |
uint64_t blocks; |
fibril_mutex_t lock; |
dev_handle_t dev_handle; |
} disk_t; |
#endif |
/** @} |
*/ |
/branches/arm/uspace/srv/bd/ata_bd/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = ata_bd |
SOURCES = \ |
ata_bd.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/bd/file_bd/file_bd.c |
---|
0,0 → 1,215 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup bd |
* @{ |
*/ |
/** |
* @file |
* @brief File-backed block device driver |
* |
* Allows accessing a file as a block device. Useful for, e.g., mounting |
* a disk image. |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <ipc/ipc.h> |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#define NAME "file_bd" |
static size_t comm_size; |
static FILE *img; |
static dev_handle_t dev_handle; |
static fibril_mutex_t dev_lock; |
static int file_bd_init(const char *fname); |
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int file_bd_read(off_t blk_idx, size_t size, void *buf); |
static int file_bd_write(off_t blk_idx, size_t size, void *buf); |
int main(int argc, char **argv) |
{ |
int rc; |
printf(NAME ": File-backed block device driver\n"); |
if (argc != 3) { |
printf("Expected two arguments (image name, device name).\n"); |
return -1; |
} |
if (file_bd_init(argv[1]) != EOK) |
return -1; |
rc = devmap_device_register(argv[2], &dev_handle); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s.\n", |
argv[2]); |
return rc; |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
static int file_bd_init(const char *fname) |
{ |
int rc; |
rc = devmap_driver_register(NAME, file_bd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver.\n"); |
return rc; |
} |
img = fopen(fname, "rb+"); |
if (img == NULL) |
return EINVAL; |
fibril_mutex_initialize(&dev_lock); |
return EOK; |
} |
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
void *fs_va = NULL; |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t method; |
int flags; |
int retval; |
off_t idx; |
size_t size; |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
if (!ipc_share_out_receive(&callid, &comm_size, &flags)) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
fs_va = as_get_mappable_page(comm_size); |
if (fs_va == NULL) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
(void) ipc_share_out_finalize(callid, fs_va); |
while (1) { |
callid = async_get_call(&call); |
method = IPC_GET_METHOD(call); |
switch (method) { |
case IPC_M_PHONE_HUNGUP: |
/* The other side has hung up. */ |
ipc_answer_0(callid, EOK); |
return; |
case BD_READ_BLOCK: |
case BD_WRITE_BLOCK: |
idx = IPC_GET_ARG1(call); |
size = IPC_GET_ARG2(call); |
if (size > comm_size) { |
retval = EINVAL; |
break; |
} |
if (method == BD_READ_BLOCK) |
retval = file_bd_read(idx, size, fs_va); |
else |
retval = file_bd_write(idx, size, fs_va); |
break; |
default: |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
static int file_bd_read(off_t blk_idx, size_t size, void *buf) |
{ |
size_t n_rd; |
fibril_mutex_lock(&dev_lock); |
fseek(img, blk_idx * size, SEEK_SET); |
n_rd = fread(buf, 1, size, img); |
if (ferror(img)) { |
fibril_mutex_unlock(&dev_lock); |
return EIO; /* Read error */ |
} |
fibril_mutex_unlock(&dev_lock); |
if (n_rd < size) |
return EINVAL; /* Read beyond end of disk */ |
return EOK; |
} |
static int file_bd_write(off_t blk_idx, size_t size, void *buf) |
{ |
size_t n_wr; |
fibril_mutex_lock(&dev_lock); |
fseek(img, blk_idx * size, SEEK_SET); |
n_wr = fread(buf, 1, size, img); |
if (ferror(img) || n_wr < size) { |
fibril_mutex_unlock(&dev_lock); |
return EIO; /* Write error */ |
} |
fibril_mutex_unlock(&dev_lock); |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/bd/file_bd/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = file_bd |
SOURCES = \ |
file_bd.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/bd/gxe_bd/gxe_bd.c |
---|
0,0 → 1,310 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup bd |
* @{ |
*/ |
/** |
* @file |
* @brief GXemul disk driver |
*/ |
#include <stdio.h> |
#include <libarch/ddi.h> |
#include <ddi.h> |
#include <ipc/ipc.h> |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <task.h> |
#define NAME "gxe_bd" |
enum { |
CTL_READ_START = 0, |
CTL_WRITE_START = 1, |
}; |
enum { |
STATUS_FAILURE = 0 |
}; |
enum { |
MAX_DISKS = 2 |
}; |
typedef struct { |
uint32_t offset_lo; |
uint32_t pad0; |
uint32_t offset_hi; |
uint32_t pad1; |
uint32_t disk_id; |
uint32_t pad2[3]; |
uint32_t control; |
uint32_t pad3[3]; |
uint32_t status; |
uint32_t pad4[3]; |
uint8_t pad5[0x3fc0]; |
uint8_t buffer[512]; |
} gxe_bd_t; |
static const size_t block_size = 512; |
static size_t comm_size; |
static uintptr_t dev_physical = 0x13000000; |
static gxe_bd_t *dev; |
static dev_handle_t dev_handle[MAX_DISKS]; |
static fibril_mutex_t dev_lock[MAX_DISKS]; |
static int gxe_bd_init(void); |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf); |
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size, |
void *buf); |
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size, |
const void *buf); |
int main(int argc, char **argv) |
{ |
printf(NAME ": GXemul disk driver\n"); |
if (gxe_bd_init() != EOK) |
return -1; |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
static int gxe_bd_init(void) |
{ |
void *vaddr; |
int rc, i; |
char name[16]; |
rc = devmap_driver_register(NAME, gxe_bd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver.\n"); |
return rc; |
} |
rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
dev = vaddr; |
for (i = 0; i < MAX_DISKS; i++) { |
snprintf(name, 16, "disk%d", i); |
rc = devmap_device_register(name, &dev_handle[i]); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s.\n", |
name); |
return rc; |
} |
fibril_mutex_initialize(&dev_lock[i]); |
} |
return EOK; |
} |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
void *fs_va = NULL; |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t method; |
dev_handle_t dh; |
int flags; |
int retval; |
off_t idx; |
size_t size; |
int disk_id, i; |
/* Get the device handle. */ |
dh = IPC_GET_ARG1(*icall); |
/* Determine which disk device is the client connecting to. */ |
disk_id = -1; |
for (i = 0; i < MAX_DISKS; i++) |
if (dev_handle[i] == dh) |
disk_id = i; |
if (disk_id < 0) { |
ipc_answer_0(iid, EINVAL); |
return; |
} |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
if (!ipc_share_out_receive(&callid, &comm_size, &flags)) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
fs_va = as_get_mappable_page(comm_size); |
if (fs_va == NULL) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
(void) ipc_share_out_finalize(callid, fs_va); |
while (1) { |
callid = async_get_call(&call); |
method = IPC_GET_METHOD(call); |
switch (method) { |
case IPC_M_PHONE_HUNGUP: |
/* The other side has hung up. */ |
ipc_answer_0(callid, EOK); |
return; |
case BD_READ_BLOCK: |
case BD_WRITE_BLOCK: |
idx = IPC_GET_ARG1(call); |
size = IPC_GET_ARG2(call); |
if (size > comm_size) { |
retval = EINVAL; |
break; |
} |
retval = gx_bd_rdwr(disk_id, method, idx * size, |
size, fs_va); |
break; |
default: |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf) |
{ |
int rc; |
size_t now; |
while (size > 0) { |
now = size < block_size ? size : block_size; |
if (method == BD_READ_BLOCK) |
rc = gxe_bd_read_block(disk_id, offset, now, buf); |
else |
rc = gxe_bd_write_block(disk_id, offset, now, buf); |
if (rc != EOK) |
return rc; |
buf += block_size; |
offset += block_size; |
if (size > block_size) |
size -= block_size; |
else |
size = 0; |
} |
return EOK; |
} |
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size, |
void *buf) |
{ |
uint32_t status; |
size_t i; |
uint32_t w; |
fibril_mutex_lock(&dev_lock[disk_id]); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
pio_write_32(&dev->control, CTL_READ_START); |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EIO; |
} |
for (i = 0; i < size; i++) { |
((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]); |
} |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EOK; |
} |
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size, |
const void *buf) |
{ |
uint32_t status; |
size_t i; |
for (i = 0; i < size; i++) { |
pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]); |
} |
fibril_mutex_lock(&dev_lock[disk_id]); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
pio_write_32(&dev->control, CTL_WRITE_START); |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EIO; |
} |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/bd/gxe_bd/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = gxe_bd |
SOURCES = \ |
gxe_bd.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/bd/rd/rd.c |
---|
0,0 → 1,241 |
/* |
* Copyright (c) 2007 Michal Konopa |
* Copyright (c) 2007 Martin Jelen |
* Copyright (c) 2007 Peter Majer |
* Copyright (c) 2007 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup rd |
* @{ |
*/ |
/** |
* @file rd.c |
* @brief Initial RAM disk for HelenOS. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/ns.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include <align.h> |
#include <bool.h> |
#include <errno.h> |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <fibril_sync.h> |
#include <stdio.h> |
#include <devmap.h> |
#include <ipc/bd.h> |
#define NAME "rd" |
/** Pointer to the ramdisk's image. */ |
static void *rd_addr; |
/** Size of the ramdisk. */ |
static size_t rd_size; |
/** |
* This rwlock protects the ramdisk's data. |
* If we were to serve multiple requests (read + write or several writes) |
* concurrently (i.e. from two or more threads), each read and write needs to be |
* protected by this rwlock. |
*/ |
fibril_rwlock_t rd_lock; |
/** Handle one connection to ramdisk. |
* |
* @param iid Hash of the request that opened the connection. |
* @param icall Call data of the request that opened the connection. |
*/ |
static void rd_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
void *fs_va = NULL; |
off_t offset; |
size_t block_size; |
size_t maxblock_size; |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
ipc_answer_0(iid, EOK); |
/* |
* Now we wait for the client to send us its communication as_area. |
*/ |
int flags; |
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) { |
fs_va = as_get_mappable_page(maxblock_size); |
if (fs_va) { |
(void) ipc_share_out_finalize(callid, fs_va); |
} else { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
} else { |
/* |
* The client doesn't speak the same protocol. |
* At this point we can't handle protocol variations. |
* Close the connection. |
*/ |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
/* |
* The other side has hung up. |
* Answer the message and exit the fibril. |
*/ |
ipc_answer_0(callid, EOK); |
return; |
case BD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Reading past the end of the device. |
*/ |
retval = ELIMIT; |
break; |
} |
fibril_rwlock_read_lock(&rd_lock); |
memcpy(fs_va, rd_addr + offset * block_size, block_size); |
fibril_rwlock_read_unlock(&rd_lock); |
retval = EOK; |
break; |
case BD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Writing past the end of the device. |
*/ |
retval = ELIMIT; |
break; |
} |
fibril_rwlock_write_lock(&rd_lock); |
memcpy(rd_addr + offset * block_size, fs_va, block_size); |
fibril_rwlock_write_unlock(&rd_lock); |
retval = EOK; |
break; |
default: |
/* |
* The client doesn't speak the same protocol. |
* Instead of closing the connection, we just ignore |
* the call. This can be useful if the client uses a |
* newer version of the protocol. |
*/ |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
/** Prepare the ramdisk image for operation. */ |
static bool rd_init(void) |
{ |
rd_size = sysinfo_value("rd.size"); |
void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical"); |
if (rd_size == 0) { |
printf(NAME ": No RAM disk found\n"); |
return false; |
} |
rd_addr = as_get_mappable_page(rd_size); |
int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE; |
int retval = physmem_map(rd_ph_addr, rd_addr, |
ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) { |
printf(NAME ": Error mapping RAM disk\n"); |
return false; |
} |
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size); |
int rc = devmap_driver_register(NAME, rd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver (%d)\n", rc); |
return false; |
} |
dev_handle_t dev_handle; |
if (devmap_device_register("initrd", &dev_handle) != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device\n"); |
return false; |
} |
fibril_rwlock_initialize(&rd_lock); |
return true; |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS RAM disk server\n"); |
if (!rd_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/bd/rd/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = rd |
SOURCES = \ |
rd.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/ns/task.c |
---|
0,0 → 1,414 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#include <ipc/ipc.h> |
#include <adt/hash_table.h> |
#include <bool.h> |
#include <errno.h> |
#include <assert.h> |
#include <stdio.h> |
#include <macros.h> |
#include "task.h" |
#include "ns.h" |
#define TASK_HASH_TABLE_CHAINS 256 |
#define P2I_HASH_TABLE_CHAINS 256 |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id); |
/* TODO: |
* |
* As there is currently no convention that each task has to be waited |
* for, the NS can leak memory because of the zombie tasks. |
* |
*/ |
/** Task hash table item. */ |
typedef struct { |
link_t link; |
task_id_t id; /**< Task ID. */ |
bool finished; /**< Task is done. */ |
bool have_rval; /**< Task returned a value. */ |
int retval; /**< The return value. */ |
} hashed_task_t; |
/** Compute hash index into task hash table. |
* |
* @param key Pointer keys. However, only the first key (i.e. truncated task |
* number) is used to compute the hash index. |
* |
* @return Hash index corresponding to key[0]. |
* |
*/ |
static hash_index_t task_hash(unsigned long *key) |
{ |
assert(key); |
return (LOWER32(*key) % TASK_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be less than or equal to 2. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
static int task_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
assert(key); |
assert(keys <= 2); |
assert(item); |
hashed_task_t *ht = hash_table_get_instance(item, hashed_task_t, link); |
if (keys == 2) |
return ((LOWER32(key[1]) == UPPER32(ht->id)) |
&& (LOWER32(key[0]) == LOWER32(ht->id))); |
else |
return (LOWER32(key[0]) == LOWER32(ht->id)); |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
static void task_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, hashed_task_t, link)); |
} |
/** Operations for task hash table. */ |
static hash_table_operations_t task_hash_table_ops = { |
.hash = task_hash, |
.compare = task_compare, |
.remove_callback = task_remove |
}; |
/** Task hash table structure. */ |
static hash_table_t task_hash_table; |
typedef struct { |
link_t link; |
ipcarg_t phash; /**< Task ID. */ |
task_id_t id; /**< Task ID. */ |
} p2i_entry_t; |
/** Compute hash index into task hash table. |
* |
* @param key Array of keys. |
* @return Hash index corresponding to key[0]. |
* |
*/ |
static hash_index_t p2i_hash(unsigned long *key) |
{ |
assert(key); |
return (*key % TASK_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be less than or equal to 1. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
assert(key); |
assert(keys == 1); |
assert(item); |
p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link); |
return (key[0] == e->phash); |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
static void p2i_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, p2i_entry_t, link)); |
} |
/** Operations for task hash table. */ |
static hash_table_operations_t p2i_ops = { |
.hash = p2i_hash, |
.compare = p2i_compare, |
.remove_callback = p2i_remove |
}; |
/** Map phone hash to task ID */ |
static hash_table_t phone_to_id; |
/** Pending task wait structure. */ |
typedef struct { |
link_t link; |
task_id_t id; /**< Task ID. */ |
ipc_callid_t callid; /**< Call ID waiting for the connection */ |
} pending_wait_t; |
static link_t pending_wait; |
int task_init(void) |
{ |
if (!hash_table_create(&task_hash_table, TASK_HASH_TABLE_CHAINS, |
2, &task_hash_table_ops)) { |
printf(NAME ": No memory available for tasks\n"); |
return ENOMEM; |
} |
if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS, |
1, &p2i_ops)) { |
printf(NAME ": No memory available for tasks\n"); |
return ENOMEM; |
} |
list_initialize(&pending_wait); |
return EOK; |
} |
/** Process pending wait requests */ |
void process_pending_wait(void) |
{ |
link_t *cur; |
task_exit_t texit; |
loop: |
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) { |
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link); |
unsigned long keys[2] = { |
LOWER32(pr->id), |
UPPER32(pr->id) |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
if (!link) |
continue; |
hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link); |
if (!ht->finished) |
continue; |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : |
TASK_EXIT_UNEXPECTED; |
ipc_answer_2(pr->callid, EOK, texit, |
ht->retval); |
} |
hash_table_remove(&task_hash_table, keys, 2); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid) |
{ |
ipcarg_t retval; |
task_exit_t texit; |
unsigned long keys[2] = { |
LOWER32(id), |
UPPER32(id) |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if (ht == NULL) { |
/* No such task exists. */ |
retval = ENOENT; |
goto out; |
} |
if (!ht->finished) { |
/* Add to pending list */ |
pending_wait_t *pr = |
(pending_wait_t *) malloc(sizeof(pending_wait_t)); |
if (!pr) { |
retval = ENOMEM; |
goto out; |
} |
pr->id = id; |
pr->callid = callid; |
list_append(&pr->link, &pending_wait); |
return; |
} |
hash_table_remove(&task_hash_table, keys, 2); |
retval = EOK; |
out: |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : TASK_EXIT_UNEXPECTED; |
ipc_answer_2(callid, retval, texit, ht->retval); |
} |
} |
int ns_task_id_intro(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
link_t *link; |
p2i_entry_t *e; |
hashed_task_t *ht; |
id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); |
keys[0] = call->in_phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link != NULL) |
return EEXISTS; |
e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t)); |
if (e == NULL) |
return ENOMEM; |
ht = (hashed_task_t *) malloc(sizeof(hashed_task_t)); |
if (ht == NULL) |
return ENOMEM; |
/* Insert to phone-to-id map. */ |
link_initialize(&e->link); |
e->phash = call->in_phone_hash; |
e->id = id; |
hash_table_insert(&phone_to_id, keys, &e->link); |
/* Insert to main table. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_initialize(&ht->link); |
ht->id = id; |
ht->finished = false; |
ht->have_rval = false; |
ht->retval = -1; |
hash_table_insert(&task_hash_table, keys, &ht->link); |
return EOK; |
} |
int ns_task_retval(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if ((ht == NULL) || ht->finished) |
return EINVAL; |
ht->finished = true; |
ht->have_rval = true; |
ht->retval = IPC_GET_ARG1(*call); |
return EOK; |
} |
int ns_task_disconnect(ipc_call_t *call) |
{ |
unsigned long keys[2]; |
task_id_t id; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
/* Delete from phone-to-id map. */ |
keys[0] = call->in_phone_hash; |
hash_table_remove(&phone_to_id, keys, 1); |
/* Mark task as finished. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = |
hash_table_get_instance(link, hashed_task_t, link); |
if (ht == NULL) |
return EOK; |
ht->finished = true; |
return EOK; |
} |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id) |
{ |
unsigned long keys[1]; |
link_t *link; |
p2i_entry_t *e; |
keys[0] = phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link == NULL) |
return ENOENT; |
e = hash_table_get_instance(link, p2i_entry_t, link); |
*id = e->id; |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/ns.c |
---|
28,77 → 28,55 |
/** @addtogroup ns |
* @{ |
*/ |
*/ |
/** |
* @file ns.c |
* @brief Naming service for HelenOS IPC. |
* @file ns.c |
* @brief Naming service for HelenOS IPC. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/ns.h> |
#include <ipc/services.h> |
#include <unistd.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <errno.h> |
#include <assert.h> |
#include <libadt/list.h> |
#include <libadt/hash_table.h> |
#include <as.h> |
#include <ddi.h> |
#include <event.h> |
#include <macros.h> |
#include <sysinfo.h> |
#include <ddi.h> |
#include <as.h> |
#include "ns.h" |
#include "service.h" |
#include "clonable.h" |
#include "task.h" |
#define NAME "ns" |
#define NS_HASH_TABLE_CHAINS 20 |
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); |
static int connect_to_service(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid); |
/* Static functions implementing NS hash table operations. */ |
static hash_index_t ns_hash(unsigned long *key); |
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item); |
static void ns_remove(link_t *item); |
/** Operations for NS hash table. */ |
static hash_table_operations_t ns_hash_table_ops = { |
.hash = ns_hash, |
.compare = ns_compare, |
.remove_callback = ns_remove |
}; |
/** NS hash table structure. */ |
static hash_table_t ns_hash_table; |
/** NS hash table item. */ |
typedef struct { |
link_t link; |
ipcarg_t service; /**< Number of the service. */ |
ipcarg_t phone; /**< Phone registered with the service. */ |
ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
} hashed_service_t; |
static void *clockaddr = NULL; |
static void *klogaddr = NULL; |
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, |
void **addr) |
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, |
size_t pages, void **addr) |
{ |
void *ph_addr; |
if (!*addr) { |
ph_addr = (void *) sysinfo_value(name); |
if (!ph_addr) { |
if (ph_addr == NULL) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
if (*addr == NULL) { |
*addr = as_get_mappable_page(pages * PAGE_SIZE); |
if (*addr == NULL) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
*addr = as_get_mappable_page(PAGE_SIZE); |
physmem_map(ph_addr, *addr, 1, |
AS_AREA_READ | AS_AREA_CACHEABLE); |
if (physmem_map(ph_addr, *addr, pages, |
AS_AREA_READ | AS_AREA_CACHEABLE) != 0) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
} |
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ); |
} |
106,30 → 84,42 |
{ |
printf(NAME ": HelenOS IPC Naming Service\n"); |
ipc_call_t call; |
ipc_callid_t callid; |
int rc = service_init(); |
if (rc != EOK) |
return rc; |
ipcarg_t retval; |
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, |
&ns_hash_table_ops)) { |
printf(NAME ": No memory available\n"); |
return ENOMEM; |
} |
rc = clonable_init(); |
if (rc != EOK) |
return rc; |
rc = task_init(); |
if (rc != EOK) |
return rc; |
printf(NAME ": Accepting connections\n"); |
while (1) { |
callid = ipc_wait_for_call(&call); |
while (true) { |
process_pending_conn(); |
process_pending_wait(); |
ipc_call_t call; |
ipc_callid_t callid = ipc_wait_for_call(&call); |
task_id_t id; |
ipcarg_t retval; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_SHARE_IN: |
switch (IPC_GET_ARG3(call)) { |
case SERVICE_MEM_REALTIME: |
get_as_area(callid, &call, "clock.faddr", |
&clockaddr); |
get_as_area(callid, &call, |
(void *) sysinfo_value("clock.faddr"), |
1, &clockaddr); |
break; |
case SERVICE_MEM_KLOG: |
get_as_area(callid, &call, "klog.faddr", |
&klogaddr); |
get_as_area(callid, &call, |
(void *) sysinfo_value("klog.faddr"), |
sysinfo_value("klog.pages"), &klogaddr); |
break; |
default: |
ipc_answer_0(callid, ENOENT); |
136,29 → 126,56 |
} |
continue; |
case IPC_M_PHONE_HUNGUP: |
retval = EOK; |
retval = ns_task_disconnect(&call); |
break; |
case IPC_M_CONNECT_TO_ME: |
/* |
* Server requests service registration. |
*/ |
retval = register_service(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call); |
if (service_clonable(IPC_GET_ARG1(call))) { |
register_clonable(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call, callid); |
continue; |
} else { |
retval = register_service(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call); |
} |
break; |
case IPC_M_CONNECT_ME_TO: |
/* |
* Client requests to be connected to a service. |
*/ |
retval = connect_to_service(IPC_GET_ARG1(call), &call, |
callid); |
if (service_clonable(IPC_GET_ARG1(call))) { |
connect_to_clonable(IPC_GET_ARG1(call), |
&call, callid); |
continue; |
} else { |
connect_to_service(IPC_GET_ARG1(call), &call, |
callid); |
continue; |
} |
break; |
case NS_PING: |
retval = EOK; |
break; |
case NS_TASK_WAIT: |
id = (task_id_t) |
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
wait_for_task(id, &call, callid); |
continue; |
case NS_ID_INTRO: |
retval = ns_task_id_intro(&call); |
break; |
case NS_RETVAL: |
retval = ns_task_retval(&call); |
break; |
default: |
retval = ENOENT; |
break; |
} |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
} |
} |
/* Not reached */ |
165,115 → 182,6 |
return 0; |
} |
/** Register service. |
* |
* @param service Service to be registered. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* |
* @return Zero on success or a value from @ref errno.h. |
*/ |
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) |
{ |
unsigned long keys[3] = { |
service, |
call->in_phone_hash, |
0 |
}; |
hashed_service_t *hs; |
if (hash_table_find(&ns_hash_table, keys)) { |
return EEXISTS; |
} |
hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
if (!hs) { |
return ENOMEM; |
} |
link_initialize(&hs->link); |
hs->service = service; |
hs->phone = phone; |
hs->in_phone_hash = call->in_phone_hash; |
hash_table_insert(&ns_hash_table, keys, &hs->link); |
return 0; |
} |
/** Connect client to service. |
* |
* @param service Service to be connected to. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* |
* @return Zero on success or a value from @ref errno.h. |
*/ |
int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) |
{ |
unsigned long keys[3] = { service, 0, 0 }; |
link_t *hlp; |
hashed_service_t *hs; |
hlp = hash_table_find(&ns_hash_table, keys); |
if (!hlp) { |
return ENOENT; |
} |
hs = hash_table_get_instance(hlp, hashed_service_t, link); |
return ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
} |
/** Compute hash index into NS hash table. |
* |
* @param key Pointer keys. However, only the first key (i.e. service number) |
* is used to compute the hash index. |
* @return Hash index corresponding to key[0]. |
*/ |
hash_index_t ns_hash(unsigned long *key) |
{ |
assert(key); |
return *key % NS_HASH_TABLE_CHAINS; |
} |
/** Compare a key with hashed item. |
* |
* This compare function always ignores the third key. |
* It exists only to make it possible to remove records |
* originating from connection with key[1] in_phone_hash |
* value. Note that this is close to being classified |
* as a nasty hack. |
* |
* @param key Array of keys. |
* @param keys Must be lesser or equal to 3. |
* @param item Pointer to a hash table item. |
* @return Non-zero if the key matches the item, zero otherwise. |
*/ |
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
hashed_service_t *hs; |
assert(key); |
assert(keys <= 3); |
assert(item); |
hs = hash_table_get_instance(item, hashed_service_t, link); |
if (keys == 2) |
return key[1] == hs->in_phone_hash; |
else |
return key[0] == hs->service; |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
*/ |
void ns_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, hashed_service_t, link)); |
} |
/** |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/task.h |
---|
0,0 → 1,54 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#ifndef NS_TASK_H__ |
#define NS_TASK_H__ |
#include <ipc/ipc.h> |
#include <event.h> |
extern int task_init(void); |
extern void process_pending_wait(void); |
extern void wait_notification(wait_type_t et, task_id_t id); |
extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid); |
extern int ns_task_id_intro(ipc_call_t *call); |
extern int ns_task_disconnect(ipc_call_t *call); |
extern int ns_task_retval(ipc_call_t *call); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/clonable.c |
---|
0,0 → 1,143 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <adt/list.h> |
#include <bool.h> |
#include <errno.h> |
#include <assert.h> |
#include <stdio.h> |
#include <malloc.h> |
#include <loader/loader.h> |
#include "clonable.h" |
#include "ns.h" |
/** Request for connection to a clonable service. */ |
typedef struct { |
link_t link; |
ipcarg_t service; |
ipc_call_t call; |
ipc_callid_t callid; |
} cs_req_t; |
/** List of clonable-service connection requests. */ |
static link_t cs_req; |
int clonable_init(void) |
{ |
list_initialize(&cs_req); |
return EOK; |
} |
/** Return true if @a service is clonable. */ |
bool service_clonable(int service) |
{ |
return (service == SERVICE_LOAD); |
} |
/** Register clonable service. |
* |
* @param service Service to be registered. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* |
*/ |
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, |
ipc_callid_t callid) |
{ |
if (list_empty(&cs_req)) { |
/* There was no pending connection request. */ |
printf(NAME ": Unexpected clonable server.\n"); |
ipc_answer_0(callid, EBUSY); |
return; |
} |
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link); |
list_remove(&csr->link); |
/* Currently we can only handle a single type of clonable service. */ |
assert(csr->service == SERVICE_LOAD); |
ipc_answer_0(callid, EOK); |
ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call), |
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE); |
free(csr); |
ipc_hangup(phone); |
} |
/** Connect client to clonable service. |
* |
* @param service Service to be connected to. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
void connect_to_clonable(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid) |
{ |
assert(service == SERVICE_LOAD); |
cs_req_t *csr = malloc(sizeof(cs_req_t)); |
if (csr == NULL) { |
ipc_answer_0(callid, ENOMEM); |
return; |
} |
/* Spawn a loader. */ |
int rc = loader_spawn("loader"); |
if (rc < 0) { |
free(csr); |
ipc_answer_0(callid, rc); |
return; |
} |
csr->service = service; |
csr->call = *call; |
csr->callid = callid; |
/* |
* We can forward the call only after the server we spawned connects |
* to us. Meanwhile we might need to service more connection requests. |
* Thus we store the call in a queue. |
*/ |
list_append(&csr->link, &cs_req); |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/service.c |
---|
0,0 → 1,254 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#include <ipc/ipc.h> |
#include <adt/hash_table.h> |
#include <assert.h> |
#include <errno.h> |
#include "service.h" |
#include "ns.h" |
#define SERVICE_HASH_TABLE_CHAINS 20 |
/** Service hash table item. */ |
typedef struct { |
link_t link; |
ipcarg_t service; /**< Number of the service. */ |
ipcarg_t phone; /**< Phone registered with the service. */ |
ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
} hashed_service_t; |
/** Compute hash index into service hash table. |
* |
* @param key Pointer keys. However, only the first key (i.e. service number) |
* is used to compute the hash index. |
* |
* @return Hash index corresponding to key[0]. |
* |
*/ |
static hash_index_t service_hash(unsigned long *key) |
{ |
assert(key); |
return (*key % SERVICE_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
* |
* This compare function always ignores the third key. |
* It exists only to make it possible to remove records |
* originating from connection with key[1] in_phone_hash |
* value. Note that this is close to being classified |
* as a nasty hack. |
* |
* @param key Array of keys. |
* @param keys Must be lesser or equal to 3. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
static int service_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
assert(key); |
assert(keys <= 3); |
assert(item); |
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link); |
if (keys == 2) |
return (key[1] == hs->in_phone_hash); |
else |
return (key[0] == hs->service); |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
static void service_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, hashed_service_t, link)); |
} |
/** Operations for service hash table. */ |
static hash_table_operations_t service_hash_table_ops = { |
.hash = service_hash, |
.compare = service_compare, |
.remove_callback = service_remove |
}; |
/** Service hash table structure. */ |
static hash_table_t service_hash_table; |
/** Pending connection structure. */ |
typedef struct { |
link_t link; |
ipcarg_t service; /**< Number of the service. */ |
ipc_callid_t callid; /**< Call ID waiting for the connection */ |
ipcarg_t arg2; /**< Second argument */ |
ipcarg_t arg3; /**< Third argument */ |
} pending_conn_t; |
static link_t pending_conn; |
int service_init(void) |
{ |
if (!hash_table_create(&service_hash_table, SERVICE_HASH_TABLE_CHAINS, |
3, &service_hash_table_ops)) { |
printf(NAME ": No memory available for services\n"); |
return ENOMEM; |
} |
list_initialize(&pending_conn); |
return EOK; |
} |
/** Process pending connection requests */ |
void process_pending_conn(void) |
{ |
link_t *cur; |
loop: |
for (cur = pending_conn.next; cur != &pending_conn; cur = cur->next) { |
pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link); |
unsigned long keys[3] = { |
pr->service, |
0, |
0 |
}; |
link_t *link = hash_table_find(&service_hash_table, keys); |
if (!link) |
continue; |
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); |
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone, |
pr->arg2, pr->arg3, 0, IPC_FF_NONE); |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, retval); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
/** Register service. |
* |
* @param service Service to be registered. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) |
{ |
unsigned long keys[3] = { |
service, |
call->in_phone_hash, |
0 |
}; |
if (hash_table_find(&service_hash_table, keys)) |
return EEXISTS; |
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
if (!hs) |
return ENOMEM; |
link_initialize(&hs->link); |
hs->service = service; |
hs->phone = phone; |
hs->in_phone_hash = call->in_phone_hash; |
hash_table_insert(&service_hash_table, keys, &hs->link); |
return 0; |
} |
/** Connect client to service. |
* |
* @param service Service to be connected to. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) |
{ |
ipcarg_t retval; |
unsigned long keys[3] = { |
service, |
0, |
0 |
}; |
link_t *link = hash_table_find(&service_hash_table, keys); |
if (!link) { |
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) { |
/* Blocking connection, add to pending list */ |
pending_conn_t *pr = |
(pending_conn_t *) malloc(sizeof(pending_conn_t)); |
if (!pr) { |
retval = ENOMEM; |
goto out; |
} |
pr->service = service; |
pr->callid = callid; |
pr->arg2 = IPC_GET_ARG2(*call); |
pr->arg3 = IPC_GET_ARG3(*call); |
list_append(&pr->link, &pending_conn); |
return; |
} |
retval = ENOENT; |
goto out; |
} |
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); |
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
out: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/clonable.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#ifndef NS_CLONABLE_H__ |
#define NS_CLONABLE_H__ |
#include <ipc/ipc.h> |
#include <bool.h> |
extern int clonable_init(void); |
extern bool service_clonable(int service); |
extern void register_clonable(ipcarg_t service, ipcarg_t phone, |
ipc_call_t *call, ipc_callid_t callid); |
extern void connect_to_clonable(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/ns.h |
---|
0,0 → 1,42 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#ifndef NS_NS_H__ |
#define NS_NS_H__ |
#define NAME "ns" |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/service.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ns |
* @{ |
*/ |
#ifndef NS_SERVICE_H__ |
#define NS_SERVICE_H__ |
#include <ipc/ipc.h> |
extern int service_init(void); |
extern void process_pending_conn(void); |
extern int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); |
extern void connect_to_service(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/ns/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
40,7 → 41,10 |
OUTPUT = ns |
SOURCES = \ |
ns.c |
ns.c \ |
service.c \ |
clonable.c \ |
task.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
51,18 → 55,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/loader/main.c |
---|
27,12 → 27,12 |
*/ |
/** @addtogroup loader |
* @brief Loads and runs programs from VFS. |
* @brief Loads and runs programs from VFS. |
* @{ |
*/ |
*/ |
/** |
* @file |
* @brief Loads and runs programs from VFS. |
* @brief Loads and runs programs from VFS. |
* |
* The program loader is a special init binary. Its image is used |
* to create a new task upon a @c task_spawn syscall. The syscall |
50,20 → 50,20 |
#include <fcntl.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/loader.h> |
#include <ipc/ns.h> |
#include <macros.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
#include <string.h> |
#include <as.h> |
#include <elf.h> |
#include <elf_load.h> |
/** |
* Bias used for loading the dynamic linker. This will be soon replaced |
* by automatic placement. |
*/ |
#define RTLD_BIAS 0x80000 |
#define DPRINTF(...) |
/** Pathname of the file that will be loaded */ |
static char *pathname = NULL; |
78,28 → 78,38 |
/** Buffer holding all arguments */ |
static char *arg_buf = NULL; |
/** Number of preset files */ |
static int filc = 0; |
/** Preset files vector */ |
static fdi_node_t **filv = NULL; |
/** Buffer holding all preset files */ |
static fdi_node_t *fil_buf = NULL; |
static elf_info_t prog_info; |
static elf_info_t interp_info; |
static bool is_dyn_linked; |
/** Used to limit number of connections to one. */ |
static bool connected; |
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request) |
static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
task_id_t task_id; |
size_t len; |
task_id = task_get_id(); |
if (!ipc_data_read_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (len > sizeof(task_id)) len = sizeof(task_id); |
if (len > sizeof(task_id)) |
len = sizeof(task_id); |
ipc_data_read_finalize(callid, &task_id, len); |
ipc_answer_0(rid, EOK); |
} |
110,18 → 120,18 |
* @param rid |
* @param request |
*/ |
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
char *name_buf; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
name_buf = malloc(len + 1); |
if (!name_buf) { |
ipc_answer_0(callid, ENOMEM); |
128,15 → 138,15 |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, name_buf, len); |
ipc_answer_0(rid, EOK); |
if (pathname != NULL) { |
free(pathname); |
pathname = NULL; |
} |
name_buf[len] = '\0'; |
pathname = name_buf; |
} |
146,58 → 156,56 |
* @param rid |
* @param request |
*/ |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_len, arg_len; |
size_t buf_size, arg_size; |
char *p; |
int n; |
if (!ipc_data_write_receive(&callid, &buf_len)) { |
if (!ipc_data_write_receive(&callid, &buf_size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (arg_buf != NULL) { |
free(arg_buf); |
arg_buf = NULL; |
} |
if (argv != NULL) { |
free(argv); |
argv = NULL; |
} |
arg_buf = malloc(buf_len + 1); |
arg_buf = malloc(buf_size + 1); |
if (!arg_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, arg_buf, buf_len); |
ipc_answer_0(rid, EOK); |
arg_buf[buf_len] = '\0'; |
ipc_data_write_finalize(callid, arg_buf, buf_size); |
arg_buf[buf_size] = '\0'; |
/* |
* Count number of arguments |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
p = p + arg_len + 1; |
while (p < arg_buf + buf_size) { |
arg_size = str_size(p); |
p = p + arg_size + 1; |
++n; |
} |
/* Allocate argv */ |
argv = malloc((n + 1) * sizeof(char *)); |
if (argv == NULL) { |
free(arg_buf); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
207,18 → 215,84 |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
while (p < arg_buf + buf_size) { |
argv[n] = p; |
arg_len = strlen(p); |
p = p + arg_len + 1; |
arg_size = str_size(p); |
p = p + arg_size + 1; |
++n; |
} |
argc = n; |
argv[n] = NULL; |
ipc_answer_0(rid, EOK); |
} |
/** Receive a call setting preset files of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_size; |
if (!ipc_data_write_receive(&callid, &buf_size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if ((buf_size % sizeof(fdi_node_t)) != 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (fil_buf != NULL) { |
free(fil_buf); |
fil_buf = NULL; |
} |
if (filv != NULL) { |
free(filv); |
filv = NULL; |
} |
fil_buf = malloc(buf_size); |
if (!fil_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, fil_buf, buf_size); |
int count = buf_size / sizeof(fdi_node_t); |
/* Allocate filvv */ |
filv = malloc((count + 1) * sizeof(fdi_node_t *)); |
if (filv == NULL) { |
free(fil_buf); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Fill filv with argument pointers |
*/ |
int i; |
for (i = 0; i < count; i++) |
filv[i] = &fil_buf[i]; |
filc = count; |
filv[count] = NULL; |
ipc_answer_0(rid, EOK); |
} |
/** Load the previously selected program. |
* |
* @param rid |
225,51 → 299,43 |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static int loader_load(ipc_callid_t rid, ipc_call_t *request) |
static int ldr_load(ipc_callid_t rid, ipc_call_t *request) |
{ |
int rc; |
// printf("Load program '%s'\n", pathname); |
rc = elf_load_file(pathname, 0, &prog_info); |
if (rc < 0) { |
printf("failed to load program\n"); |
if (rc != EE_OK) { |
DPRINTF("Failed to load executable '%s'.\n", pathname); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
// printf("Create PCB\n"); |
elf_create_pcb(&prog_info, &pcb); |
pcb.argc = argc; |
pcb.argv = argv; |
pcb.filc = filc; |
pcb.filv = filv; |
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
// printf("Run statically linked program\n"); |
// printf("entry point: 0x%llx\n", prog_info.entry); |
is_dyn_linked = false; |
ipc_answer_0(rid, EOK); |
return 0; |
} |
printf("Load dynamic linker '%s'\n", prog_info.interp); |
rc = elf_load_file("/rtld.so", RTLD_BIAS, &interp_info); |
if (rc < 0) { |
printf("failed to load dynamic linker\n"); |
rc = elf_load_file(prog_info.interp, 0, &interp_info); |
if (rc != EE_OK) { |
DPRINTF("Failed to load interpreter '%s.'\n", |
prog_info.interp); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
/* |
* Provide dynamic linker with some useful data |
*/ |
pcb.rtld_dynamic = interp_info.dynamic; |
pcb.rtld_bias = RTLD_BIAS; |
is_dyn_linked = true; |
ipc_answer_0(rid, EOK); |
return 0; |
} |
280,24 → 346,28 |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static void loader_run(ipc_callid_t rid, ipc_call_t *request) |
static void ldr_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
const char *cp; |
/* Set the task name. */ |
cp = str_rchr(pathname, '/'); |
cp = (cp == NULL) ? pathname : (cp + 1); |
task_set_name(cp); |
if (is_dyn_linked == true) { |
/* Dynamically linked program */ |
printf("run dynamic linker\n"); |
printf("entry point: 0x%llx\n", interp_info.entry); |
close_console(); |
DPRINTF("Run ELF interpreter.\n"); |
DPRINTF("Entry point: 0x%lx\n", interp_info.entry); |
ipc_answer_0(rid, EOK); |
elf_run(&interp_info, &pcb); |
} else { |
/* Statically linked program */ |
close_console(); |
ipc_answer_0(rid, EOK); |
elf_run(&prog_info, &pcb); |
} |
} |
/* Not reached */ |
} |
306,33 → 376,50 |
* Receive and carry out commands (of which the last one should be |
* to execute the loaded program). |
*/ |
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall) |
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
/* Already have a connection? */ |
if (connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
connected = true; |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
/* Ignore parameters, the connection is already open */ |
(void)iid; (void)icall; |
(void) iid; |
(void) icall; |
while (1) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
exit(0); |
case LOADER_GET_TASKID: |
loader_get_taskid(callid, &call); |
ldr_get_taskid(callid, &call); |
continue; |
case LOADER_SET_PATHNAME: |
loader_set_pathname(callid, &call); |
ldr_set_pathname(callid, &call); |
continue; |
case LOADER_SET_ARGS: |
loader_set_args(callid, &call); |
ldr_set_args(callid, &call); |
continue; |
case LOADER_SET_FILES: |
ldr_set_files(callid, &call); |
continue; |
case LOADER_LOAD: |
loader_load(callid, &call); |
ldr_load(callid, &call); |
continue; |
case LOADER_RUN: |
loader_run(callid, &call); |
ldr_run(callid, &call); |
/* Not reached */ |
default: |
retval = ENOENT; |
340,7 → 427,7 |
} |
if ((callid & IPC_CALLID_NOTIFICATION) == 0 && |
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) { |
printf("responding EINVAL to method %d\n", |
DPRINTF("Responding EINVAL to method %d.\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, EINVAL); |
} |
351,31 → 438,28 |
*/ |
int main(int argc, char *argv[]) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phone_hash; |
ipcarg_t phonead; |
task_id_t id; |
int rc; |
/* The first call only communicates the incoming phone hash */ |
callid = ipc_wait_for_call(&call); |
connected = false; |
if (IPC_GET_METHOD(call) != LOADER_HELLO) { |
if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) |
ipc_answer_0(callid, EINVAL); |
return 1; |
} |
/* Introduce this task to the NS (give it our task ID). */ |
id = task_get_id(); |
rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id)); |
if (rc != EOK) |
return -1; |
ipc_answer_0(callid, EOK); |
phone_hash = call.in_phone_hash; |
/* Set a handler of incomming connections. */ |
async_set_client_connection(ldr_connection); |
/* Register at naming service. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) |
return -2; |
/* |
* Up until now async must not be used as it couldn't |
* handle incoming requests. (Which means e.g. printf() |
* cannot be used) |
*/ |
async_new_connection(phone_hash, 0, NULL, loader_connection); |
async_manager(); |
/* not reached */ |
/* Never reached */ |
return 0; |
} |
/branches/arm/uspace/srv/loader/elf_load.c |
---|
57,6 → 57,8 |
#include "elf_load.h" |
#include "arch.h" |
#define DPRINTF(...) |
static char *error_codes[] = { |
"no error", |
"invalid image", |
72,7 → 74,7 |
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); |
/** Read until the buffer is read in its entirety. */ |
static int my_read(int fd, char *buf, size_t len) |
static int my_read(int fd, void *buf, size_t len) |
{ |
int cnt = 0; |
do { |
106,11 → 108,9 |
int fd; |
int rc; |
// printf("open and read '%s'...\n", file_name); |
fd = open(file_name, O_RDONLY); |
if (fd < 0) { |
printf("failed opening file\n"); |
DPRINTF("failed opening file\n"); |
return -1; |
} |
171,19 → 171,18 |
rc = my_read(elf->fd, header, sizeof(elf_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
elf->header = header; |
// printf("ELF-load:"); |
/* Identify ELF */ |
if (header->e_ident[EI_MAG0] != ELFMAG0 || |
header->e_ident[EI_MAG1] != ELFMAG1 || |
header->e_ident[EI_MAG2] != ELFMAG2 || |
header->e_ident[EI_MAG3] != ELFMAG3) { |
printf("invalid header\n"); |
DPRINTF("Invalid header.\n"); |
return EE_INVALID; |
} |
193,18 → 192,18 |
header->e_ident[EI_VERSION] != EV_CURRENT || |
header->e_version != EV_CURRENT || |
header->e_ident[EI_CLASS] != ELF_CLASS) { |
printf("incompatible data/version/class\n"); |
DPRINTF("Incompatible data/version/class.\n"); |
return EE_INCOMPATIBLE; |
} |
if (header->e_phentsize != sizeof(elf_segment_header_t)) { |
printf("e_phentsize:%d != %d\n", header->e_phentsize, |
DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize, |
sizeof(elf_segment_header_t)); |
return EE_INCOMPATIBLE; |
} |
if (header->e_shentsize != sizeof(elf_section_header_t)) { |
printf("e_shentsize:%d != %d\n", header->e_shentsize, |
DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize, |
sizeof(elf_section_header_t)); |
return EE_INCOMPATIBLE; |
} |
211,23 → 210,19 |
/* Check if the object type is supported. */ |
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) { |
printf("Object type %d is not supported\n", header->e_type); |
DPRINTF("Object type %d is not supported\n", header->e_type); |
return EE_UNSUPPORTED; |
} |
/* Shared objects can be loaded with a bias */ |
// printf("Object type: %d\n", header->e_type); |
if (header->e_type == ET_DYN) |
elf->bias = so_bias; |
else |
elf->bias = 0; |
// printf("Bias set to 0x%x\n", elf->bias); |
elf->info->interp = NULL; |
elf->info->dynamic = NULL; |
// printf("parse segments\n"); |
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t segment_hdr; |
239,7 → 234,7 |
rc = my_read(elf->fd, &segment_hdr, |
sizeof(elf_segment_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
248,7 → 243,7 |
return rc; |
} |
// printf("parse sections\n"); |
DPRINTF("Parse sections.\n"); |
/* Inspect all section headers and proccess them. */ |
for (i = 0; i < header->e_shnum; i++) { |
261,7 → 256,7 |
rc = my_read(elf->fd, §ion_hdr, |
sizeof(elf_section_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
273,7 → 268,7 |
elf->info->entry = |
(entry_point_t)((uint8_t *)header->e_entry + elf->bias); |
// printf("done\n"); |
DPRINTF("Done.\n"); |
return EE_OK; |
} |
316,7 → 311,7 |
case PT_LOPROC: |
case PT_HIPROC: |
default: |
printf("segment p_type %d unknown\n", entry->p_type); |
DPRINTF("Segment p_type %d unknown.\n", entry->p_type); |
return EE_UNSUPPORTED; |
break; |
} |
336,21 → 331,26 |
int flags = 0; |
uintptr_t bias; |
uintptr_t base; |
void *seg_ptr; |
uintptr_t seg_addr; |
size_t mem_sz; |
int rc; |
// printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr, |
// entry->p_memsz); |
bias = elf->bias; |
seg_addr = entry->p_vaddr + bias; |
seg_ptr = (void *) seg_addr; |
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", seg_addr, |
entry->p_memsz); |
if (entry->p_align > 1) { |
if ((entry->p_offset % entry->p_align) != |
(entry->p_vaddr % entry->p_align)) { |
printf("align check 1 failed offset%%align=%d, " |
(seg_addr % entry->p_align)) { |
DPRINTF("Align check 1 failed offset%%align=%d, " |
"vaddr%%align=%d\n", |
entry->p_offset % entry->p_align, |
entry->p_vaddr % entry->p_align |
seg_addr % entry->p_align |
); |
return EE_INVALID; |
} |
369,8 → 369,8 |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
// printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias, |
// entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr, |
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
/* |
* For the course of loading, the area needs to be readable |
379,17 → 379,16 |
a = as_area_create((uint8_t *)base + bias, mem_sz, |
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); |
if (a == (void *)(-1)) { |
printf("memory mapping failed\n"); |
DPRINTF("Memory mapping failed.\n"); |
return EE_MEMORY; |
} |
// printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
// entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a); |
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
base + bias, mem_sz, flags, (uintptr_t)a); |
/* |
* Load segment data |
*/ |
// printf("seek to %d\n", entry->p_offset); |
rc = lseek(elf->fd, entry->p_offset, SEEK_SET); |
if (rc < 0) { |
printf("seek error\n"); |
396,28 → 395,25 |
return EE_INVALID; |
} |
// printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias); |
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/ |
/* Long reads are not possible yet. Load segment picewise */ |
/* Long reads are not possible yet. Load segment piecewise. */ |
unsigned left, now; |
uint8_t *dp; |
left = entry->p_filesz; |
dp = (uint8_t *)(entry->p_vaddr + bias); |
dp = seg_ptr; |
while (left > 0) { |
now = 16384; |
if (now > left) now = left; |
// printf("read %d...", now); |
rc = my_read(elf->fd, dp, now); |
// printf("->%d\n", rc); |
if (rc < 0) { |
printf("read error\n"); |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
425,16 → 421,15 |
dp += now; |
} |
// printf("set area flags to %d\n", flags); |
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags); |
rc = as_area_change_flags(seg_ptr, flags); |
if (rc != 0) { |
printf("failed to set memory area flags\n"); |
DPRINTF("Failed to set memory area flags.\n"); |
return EE_MEMORY; |
} |
if (flags & AS_AREA_EXEC) { |
/* Enforce SMC coherence for the segment */ |
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz)) |
if (smc_coherence(seg_ptr, entry->p_filesz)) |
return EE_MEMORY; |
} |
465,7 → 460,7 |
/* Record pointer to dynamic section into info structure */ |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
printf("dynamic section found at 0x%x\n", |
DPRINTF("Dynamic section found at 0x%x.\n", |
(uintptr_t)elf->info->dynamic); |
break; |
default: |
/branches/arm/uspace/srv/loader/arch/ia32/ia32.s |
---|
46,4 → 46,4 |
# Save a tiny bit of stack space |
pop %ebp |
jmp %eax |
jmp *%eax |
/branches/arm/uspace/srv/loader/arch/ia32/_link.ld.in |
---|
1,8 → 1,8 |
/* |
/* |
* The difference from _link.ld.in for regular statically-linked apps |
* is the base address and the special interp section. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/ia32/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia32.s |
ARCH_SOURCES := arch/$(UARCH)/ia32.s |
/branches/arm/uspace/srv/loader/arch/sparc64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/sparc64/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/sparc64.s |
ARCH_SOURCES := arch/$(UARCH)/sparc64.s |
/branches/arm/uspace/srv/loader/arch/ia64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
12,15 → 12,10 |
*(.interp); |
} :interp |
. = 0x00084000 + SIZEOF_HEADERS; |
/* On Itanium code sections must be aligned to 16 bytes. */ |
. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16); |
.init : { |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
*(.init); |
} : text |
.text : { |
/branches/arm/uspace/srv/loader/arch/ia64/Makefile.inc |
---|
27,5 → 27,5 |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia64.s |
ARCH_SOURCES := arch/$(UARCH)/ia64.s |
AFLAGS += -xexplicit |
/branches/arm/uspace/srv/loader/arch/arm32/_link.ld.in |
---|
1,8 → 1,8 |
/* |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/arm32/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/arm32.s |
ARCH_SOURCES := arch/$(UARCH)/arm32.s |
/branches/arm/uspace/srv/loader/arch/ppc32/_link.ld.in |
---|
1,8 → 1,8 |
/* |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/ppc32/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ppc32.s |
ARCH_SOURCES := arch/$(UARCH)/ppc32.s |
/branches/arm/uspace/srv/loader/arch/ppc32/ppc32.s |
---|
36,5 → 36,5 |
# Jump to a program entry point |
program_run: |
mtctr %r3 |
mr %r3, %r4 # Pass pcb to the entry point in %r3 |
mr %r6, %r4 # Pass pcb to the entry point in %r6 |
bctr |
/branches/arm/uspace/srv/loader/arch/amd64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/amd64/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/amd64.s |
ARCH_SOURCES := arch/$(UARCH)/amd64.s |
/branches/arm/uspace/srv/loader/arch/mips32/_link.ld.in |
---|
1,8 → 1,8 |
/* |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/arm/uspace/srv/loader/arch/mips32/Makefile.inc |
---|
27,4 → 27,4 |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/mips32.s |
ARCH_SOURCES := arch/$(UARCH)/mips32.s |
/branches/arm/uspace/srv/loader/arch/mips32eb |
---|
0,0 → 1,0 |
link mips32 |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/arm/uspace/srv/loader/Makefile |
---|
27,30 → 27,19 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include arch/$(ARCH)/Makefile.inc |
include arch/$(UARCH)/Makefile.inc |
CFLAGS += -Iinclude |
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
## Sources |
# |
70,18 → 59,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(ARCH)/_link.ld Makefile.depend |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(UARCH)/_link.ld Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(ARCH)/_link.ld |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map |
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(UARCH)/_link.ld |
$(LD) -T arch/$(UARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
/branches/arm/uspace/srv/fs/devfs/devfs_ops.c |
---|
0,0 → 1,531 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file devfs_ops.c |
* @brief Implementation of VFS operations for the devfs file system server. |
*/ |
#include <ipc/ipc.h> |
#include <bool.h> |
#include <errno.h> |
#include <malloc.h> |
#include <string.h> |
#include <libfs.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <sys/stat.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE]) |
/** Opened devices structure */ |
typedef struct { |
dev_handle_t handle; |
int phone; |
size_t refcount; |
link_t link; |
} device_t; |
/** Hash table of opened devices */ |
static hash_table_t devices; |
/** Hash table mutex */ |
static FIBRIL_MUTEX_INITIALIZE(devices_mutex); |
#define DEVICES_KEYS 1 |
#define DEVICES_KEY_HANDLE 0 |
#define DEVICES_BUCKETS 256 |
/* Implementation of hash table interface for the nodes hash table. */ |
static hash_index_t devices_hash(unsigned long key[]) |
{ |
return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS; |
} |
static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
device_t *dev = hash_table_get_instance(item, device_t, link); |
return (dev->handle == (dev_handle_t) key[DEVICES_KEY_HANDLE]); |
} |
static void devices_remove_callback(link_t *item) |
{ |
free(hash_table_get_instance(item, device_t, link)); |
} |
static hash_table_operations_t devices_ops = { |
.hash = devices_hash, |
.compare = devices_compare, |
.remove_callback = devices_remove_callback |
}; |
bool devfs_init(void) |
{ |
if (!hash_table_create(&devices, DEVICES_BUCKETS, |
DEVICES_KEYS, &devices_ops)) |
return false; |
if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0) |
return false; |
return true; |
} |
void devfs_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
free(opts); |
ipc_answer_3(rid, EOK, 0, 0, 0); |
} |
void devfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipcarg_t first = IPC_GET_ARG1(*request); |
ipcarg_t last = IPC_GET_ARG2(*request); |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
ipcarg_t lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); |
/* Hierarchy is flat, no altroot is supported */ |
if (index != 0) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
if ((lflag & L_LINK) || (lflag & L_UNLINK)) { |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* Eat slash */ |
if (PLB_GET_CHAR(first) == '/') { |
first++; |
first %= PLB_SIZE; |
} |
if (first >= last) { |
/* Root entry */ |
if (!(lflag & L_FILE)) |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0); |
else |
ipc_answer_0(rid, ENOENT); |
} else { |
if (!(lflag & L_DIRECTORY)) { |
size_t len; |
if (last >= first) |
len = last - first + 1; |
else |
len = first + PLB_SIZE - last + 1; |
char *name = (char *) malloc(len + 1); |
if (name == NULL) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
size_t i; |
for (i = 0; i < len; i++) |
name[i] = PLB_GET_CHAR(first + i); |
name[len] = 0; |
dev_handle_t handle; |
if (devmap_device_get_handle(name, &handle, 0) != EOK) { |
free(name); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
if (lflag & L_OPEN) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
fibril_mutex_unlock(&devices_mutex); |
free(name); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
free(name); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev->handle = handle; |
dev->phone = phone; |
dev->refcount = 1; |
hash_table_insert(&devices, key, &dev->link); |
} else { |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
fibril_mutex_unlock(&devices_mutex); |
} |
free(name); |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1); |
} else |
ipc_answer_0(rid, ENOENT); |
} |
} |
void devfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t handle = IPC_GET_ARG2(*request); |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev->handle = handle; |
dev->phone = phone; |
dev->refcount = 1; |
hash_table_insert(&devices, key, &dev->link); |
} else { |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_3(rid, EOK, 0, 1, L_FILE); |
} |
void devfs_stat(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); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size) || |
size != sizeof(struct stat)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
struct stat stat; |
memset(&stat, 0, sizeof(struct stat)); |
stat.fs_handle = devfs_reg.fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = 1; |
stat.is_file = (index != 0); |
stat.size = 0; |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk != NULL) |
stat.devfs_stat.device = (dev_handle_t)index; |
fibril_mutex_unlock(&devices_mutex); |
} |
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
void devfs_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
ipc_callid_t callid; |
if (!ipc_data_read_receive(&callid, NULL)) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), |
IPC_GET_ARG3(*request), &answer); |
/* Forward the IPC_M_DATA_READ request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_1(rid, rc, bytes); |
} else { |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
size_t count = devmap_device_get_count(); |
dev_desc_t *desc = malloc(count * sizeof(dev_desc_t)); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_1(rid, ENOMEM, 0); |
return; |
} |
size_t max = devmap_device_get_devices(count, desc); |
if (pos < max) { |
ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1); |
} else { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
free(desc); |
ipc_answer_1(rid, EOK, 1); |
} |
} |
void devfs_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, NULL)) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), |
IPC_GET_ARG3(*request), &answer); |
/* Forward the IPC_M_DATA_WRITE request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_1(rid, rc, bytes); |
} else { |
/* Read-only filesystem */ |
ipc_answer_0(rid, ENOTSUP); |
} |
} |
void devfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount--; |
if (dev->refcount == 0) { |
ipc_hangup(dev->phone); |
hash_table_remove(&devices, key, DEVICES_KEYS); |
} |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, EOK); |
} else |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
/* Make a request at the driver */ |
ipc_call_t answer; |
aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
/* Driver reply is the final result of the whole operation */ |
ipc_answer_0(rid, rc); |
} else |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_destroy(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/devfs/devfs.c |
---|
0,0 → 1,141 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file devfs.c |
* @brief Devices file system. |
* |
* Every device registered to device mapper is represented as a file in this |
* file system. |
*/ |
#include <stdio.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <async.h> |
#include <errno.h> |
#include <libfs.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
#define NAME "devfs" |
static vfs_info_t devfs_vfs_info = { |
.name = "devfs", |
}; |
fs_reg_t devfs_reg; |
static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
if (iid) |
ipc_answer_0(iid, EOK); |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
devfs_mounted(callid, &call); |
break; |
case VFS_OUT_MOUNT: |
devfs_mount(callid, &call); |
break; |
case VFS_OUT_LOOKUP: |
devfs_lookup(callid, &call); |
break; |
case VFS_OUT_OPEN_NODE: |
devfs_open_node(callid, &call); |
break; |
case VFS_OUT_STAT: |
devfs_stat(callid, &call); |
break; |
case VFS_OUT_READ: |
devfs_read(callid, &call); |
break; |
case VFS_OUT_WRITE: |
devfs_write(callid, &call); |
break; |
case VFS_OUT_TRUNCATE: |
devfs_truncate(callid, &call); |
break; |
case VFS_OUT_CLOSE: |
devfs_close(callid, &call); |
break; |
case VFS_OUT_SYNC: |
devfs_sync(callid, &call); |
break; |
case VFS_OUT_DESTROY: |
devfs_destroy(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
} |
} |
} |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Device Filesystem\n"); |
if (!devfs_init()) { |
printf(NAME ": failed to initialize devfs\n"); |
return -1; |
} |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
return -1; |
} |
int rc = fs_register(vfs_phone, &devfs_reg, &devfs_vfs_info, |
devfs_connection); |
if (rc != EOK) { |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/devfs/devfs_ops.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef DEVFS_DEVFS_OPS_H_ |
#define DEVFS_DEVFS_OPS_H_ |
#include <ipc/ipc.h> |
#include <bool.h> |
extern bool devfs_init(void); |
extern void devfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void devfs_mount(ipc_callid_t, ipc_call_t *); |
extern void devfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void devfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void devfs_stat(ipc_callid_t, ipc_call_t *); |
extern void devfs_sync(ipc_callid_t, ipc_call_t *); |
extern void devfs_read(ipc_callid_t, ipc_call_t *); |
extern void devfs_write(ipc_callid_t, ipc_call_t *); |
extern void devfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void devfs_close(ipc_callid_t, ipc_call_t *); |
extern void devfs_destroy(ipc_callid_t, ipc_call_t *); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/devfs/Makefile |
---|
0,0 → 1,82 |
# |
# Copyright (c) 2005 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = devfs |
SOURCES = \ |
devfs.c \ |
devfs_ops.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/fs/devfs/devfs.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef DEVFS_DEVFS_H_ |
#define DEVFS_DEVFS_H_ |
#include <libfs.h> |
extern fs_reg_t devfs_reg; |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
47,7 → 47,7 |
#include <stdio.h> |
#include <assert.h> |
#include <sys/types.h> |
#include <libadt/hash_table.h> |
#include <adt/hash_table.h> |
#include <as.h> |
#include <libfs.h> |
54,53 → 54,50 |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define DENTRIES_BUCKETS 256 |
#define NODES_BUCKETS 256 |
#define NAMES_BUCKETS 4 |
/** All root nodes have index 0. */ |
#define TMPFS_SOME_ROOT 0 |
/** Global counter for assigning node indices. Shared by all instances. */ |
fs_index_t tmpfs_next_index = 1; |
/* |
* For now, we don't distinguish between different dev_handles/instances. All |
* requests resolve to the only instance, rooted in the following variable. |
*/ |
static tmpfs_dentry_t *root; |
/* |
* Implementation of the libfs interface. |
*/ |
/* Forward declarations of static functions. */ |
static void *tmpfs_match(void *, const char *); |
static void *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(void *); |
static void *tmpfs_create_node(int); |
static bool tmpfs_link_node(void *, void *, const char *); |
static int tmpfs_unlink_node(void *, void *); |
static int tmpfs_destroy_node(void *); |
static fs_node_t *tmpfs_match(fs_node_t *, const char *); |
static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(fs_node_t *); |
static fs_node_t *tmpfs_create_node(dev_handle_t, int); |
static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *); |
static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *); |
static int tmpfs_destroy_node(fs_node_t *); |
/* Implementation of helper functions. */ |
static fs_index_t tmpfs_index_get(void *nodep) |
static fs_index_t tmpfs_index_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->index; |
return TMPFS_NODE(fn)->index; |
} |
static size_t tmpfs_size_get(void *nodep) |
static size_t tmpfs_size_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->size; |
return TMPFS_NODE(fn)->size; |
} |
static unsigned tmpfs_lnkcnt_get(void *nodep) |
static unsigned tmpfs_lnkcnt_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->lnkcnt; |
return TMPFS_NODE(fn)->lnkcnt; |
} |
static bool tmpfs_has_children(void *nodep) |
static bool tmpfs_has_children(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->child != NULL; |
return !list_empty(&TMPFS_NODE(fn)->cs_head); |
} |
static void *tmpfs_root_get(dev_handle_t dev_handle) |
static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle) |
{ |
return root; |
return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT); |
} |
static char tmpfs_plb_get_char(unsigned pos) |
108,14 → 105,14 |
return tmpfs_reg.plb_ro[pos % PLB_SIZE]; |
} |
static bool tmpfs_is_directory(void *nodep) |
static bool tmpfs_is_directory(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY; |
return TMPFS_NODE(fn)->type == TMPFS_DIRECTORY; |
} |
static bool tmpfs_is_file(void *nodep) |
static bool tmpfs_is_file(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE; |
return TMPFS_NODE(fn)->type == TMPFS_FILE; |
} |
/** libfs operations */ |
137,259 → 134,231 |
.is_file = tmpfs_is_file |
}; |
/** Hash table of all directory entries. */ |
hash_table_t dentries; |
/** Hash table of all TMPFS nodes. */ |
hash_table_t nodes; |
/* Implementation of hash table interface for the dentries hash table. */ |
static hash_index_t dentries_hash(unsigned long *key) |
{ |
return *key % DENTRIES_BUCKETS; |
} |
#define NODES_KEY_INDEX 0 |
#define NODES_KEY_DEV 1 |
static int dentries_compare(unsigned long *key, hash_count_t keys, |
link_t *item) |
/* Implementation of hash table interface for the nodes hash table. */ |
static hash_index_t nodes_hash(unsigned long key[]) |
{ |
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t, |
dh_link); |
return dentry->index == *key; |
return key[NODES_KEY_INDEX] % NODES_BUCKETS; |
} |
static void dentries_remove_callback(link_t *item) |
static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t, |
nh_link); |
return (nodep->index == key[NODES_KEY_INDEX] && |
nodep->dev_handle == key[NODES_KEY_DEV]); |
} |
/** TMPFS dentries hash table operations. */ |
hash_table_operations_t dentries_ops = { |
.hash = dentries_hash, |
.compare = dentries_compare, |
.remove_callback = dentries_remove_callback |
}; |
fs_index_t tmpfs_next_index = 1; |
typedef struct { |
char *name; |
tmpfs_dentry_t *parent; |
link_t link; |
} tmpfs_name_t; |
/* Implementation of hash table interface for the names hash table. */ |
static hash_index_t names_hash(unsigned long *key) |
static void nodes_remove_callback(link_t *item) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
return dentry->index % NAMES_BUCKETS; |
} |
static int names_compare(unsigned long *key, hash_count_t keys, link_t *item) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
return dentry == namep->parent; |
} |
static void names_remove_callback(link_t *item) |
{ |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
free(namep->name); |
free(namep); |
} |
/** TMPFS node names hash table operations. */ |
static hash_table_operations_t names_ops = { |
.hash = names_hash, |
.compare = names_compare, |
.remove_callback = names_remove_callback |
/** TMPFS nodes hash table operations. */ |
hash_table_operations_t nodes_ops = { |
.hash = nodes_hash, |
.compare = nodes_compare, |
.remove_callback = nodes_remove_callback |
}; |
static void tmpfs_name_initialize(tmpfs_name_t *namep) |
static void tmpfs_node_initialize(tmpfs_node_t *nodep) |
{ |
namep->name = NULL; |
namep->parent = NULL; |
link_initialize(&namep->link); |
nodep->bp = NULL; |
nodep->index = 0; |
nodep->dev_handle = 0; |
nodep->type = TMPFS_NONE; |
nodep->lnkcnt = 0; |
nodep->size = 0; |
nodep->data = NULL; |
link_initialize(&nodep->nh_link); |
list_initialize(&nodep->cs_head); |
} |
static bool tmpfs_dentry_initialize(tmpfs_dentry_t *dentry) |
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentryp) |
{ |
dentry->index = 0; |
dentry->sibling = NULL; |
dentry->child = NULL; |
dentry->type = TMPFS_NONE; |
dentry->lnkcnt = 0; |
dentry->size = 0; |
dentry->data = NULL; |
link_initialize(&dentry->dh_link); |
return (bool)hash_table_create(&dentry->names, NAMES_BUCKETS, 1, |
&names_ops); |
link_initialize(&dentryp->link); |
dentryp->name = NULL; |
dentryp->node = NULL; |
} |
static bool tmpfs_init(void) |
bool tmpfs_init(void) |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops)) |
return false; |
root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return false; |
} |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
/** Compare one component of path to a directory entry. |
* |
* @param parentp Pointer to node from which we descended. |
* @param childp Pointer to node to compare the path component with. |
* @param component Array of characters holding component name. |
* |
* @return True on match, false otherwise. |
*/ |
static bool |
tmpfs_match_one(tmpfs_dentry_t *parentp, tmpfs_dentry_t *childp, |
const char *component) |
static bool tmpfs_instance_init(dev_handle_t dev_handle) |
{ |
unsigned long key = (unsigned long) parentp; |
link_t *hlp = hash_table_find(&childp->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, link); |
return !strcmp(namep->name, component); |
fs_node_t *rfn; |
rfn = tmpfs_create_node(dev_handle, L_DIRECTORY); |
if (!rfn) |
return false; |
TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
void *tmpfs_match(void *prnt, const char *component) |
fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = parentp->child; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
link_t *lnk; |
while (childp && !tmpfs_match_one(parentp, childp, component)) |
childp = childp->sibling; |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t, |
link); |
if (!str_cmp(dentryp->name, component)) |
return FS_NODE(dentryp->node); |
} |
return (void *) childp; |
return NULL; |
} |
void * |
tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
unsigned long key = index; |
link_t *lnk = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
link_t *lnk = hash_table_find(&nodes, key); |
if (!lnk) |
return NULL; |
return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link); |
return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link)); |
} |
void tmpfs_node_put(void *node) |
void tmpfs_node_put(fs_node_t *fn) |
{ |
/* nothing to do */ |
} |
void *tmpfs_create_node(int lflag) |
fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag) |
{ |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t)); |
if (!node) |
tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t)); |
if (!nodep) |
return NULL; |
if (!tmpfs_dentry_initialize(node)) { |
free(node); |
tmpfs_node_initialize(nodep); |
nodep->bp = malloc(sizeof(fs_node_t)); |
if (!nodep->bp) { |
free(nodep); |
return NULL; |
} |
node->index = tmpfs_next_index++; |
fs_node_initialize(nodep->bp); |
nodep->bp->data = nodep; /* link the FS and TMPFS nodes */ |
if (!tmpfs_root_get(dev_handle)) |
nodep->index = TMPFS_SOME_ROOT; |
else |
nodep->index = tmpfs_next_index++; |
nodep->dev_handle = dev_handle; |
if (lflag & L_DIRECTORY) |
node->type = TMPFS_DIRECTORY; |
nodep->type = TMPFS_DIRECTORY; |
else |
node->type = TMPFS_FILE; |
nodep->type = TMPFS_FILE; |
/* Insert the new node into the dentry hash table. */ |
unsigned long key = node->index; |
hash_table_insert(&dentries, &key, &node->dh_link); |
return (void *) node; |
/* Insert the new node into the nodes hash table. */ |
unsigned long key[] = { |
[NODES_KEY_INDEX] = nodep->index, |
[NODES_KEY_DEV] = nodep->dev_handle |
}; |
hash_table_insert(&nodes, key, &nodep->nh_link); |
return FS_NODE(nodep); |
} |
bool tmpfs_link_node(void *prnt, void *chld, const char *nm) |
int tmpfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
tmpfs_node_t *childp = TMPFS_NODE(cfn); |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
assert(parentp->type == TMPFS_DIRECTORY); |
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t)); |
if (!namep) |
return false; |
tmpfs_name_initialize(namep); |
size_t len = strlen(nm); |
namep->name = malloc(len + 1); |
if (!namep->name) { |
free(namep); |
return false; |
/* Check for duplicit entries. */ |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
if (!str_cmp(dentryp->name, nm)) |
return EEXIST; |
} |
strcpy(namep->name, nm); |
namep->parent = parentp; |
childp->lnkcnt++; |
unsigned long key = (unsigned long) parentp; |
hash_table_insert(&childp->names, &key, &namep->link); |
/* Allocate and initialize the dentry. */ |
dentryp = malloc(sizeof(tmpfs_dentry_t)); |
if (!dentryp) |
return ENOMEM; |
tmpfs_dentry_initialize(dentryp); |
/* Insert the new node into the namespace. */ |
if (parentp->child) { |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling) |
tmp = tmp->sibling; |
tmp->sibling = childp; |
} else { |
parentp->child = childp; |
/* Populate and link the new dentry. */ |
size_t size = str_size(nm); |
dentryp->name = malloc(size + 1); |
if (!dentryp->name) { |
free(dentryp); |
return ENOMEM; |
} |
str_cpy(dentryp->name, size + 1, nm); |
dentryp->node = childp; |
childp->lnkcnt++; |
list_append(&dentryp->link, &parentp->cs_head); |
return true; |
return EOK; |
} |
int tmpfs_unlink_node(void *prnt, void *chld) |
int tmpfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *)prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *)chld; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
tmpfs_node_t *childp = NULL; |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
if (!parentp) |
return EBUSY; |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
if (!str_cmp(dentryp->name, nm)) { |
childp = dentryp->node; |
assert(FS_NODE(childp) == cfn); |
break; |
} |
} |
if (childp->child) |
if (!childp) |
return ENOENT; |
if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head)) |
return ENOTEMPTY; |
if (parentp->child == childp) { |
parentp->child = childp->sibling; |
} else { |
/* TODO: consider doubly linked list for organizing siblings. */ |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling != childp) |
tmp = tmp->sibling; |
tmp->sibling = childp->sibling; |
} |
childp->sibling = NULL; |
unsigned long key = (unsigned long) parentp; |
hash_table_remove(&childp->names, &key, 1); |
list_remove(&dentryp->link); |
free(dentryp); |
childp->lnkcnt--; |
return EOK; |
} |
int tmpfs_destroy_node(void *nodep) |
int tmpfs_destroy_node(fs_node_t *fn) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep; |
tmpfs_node_t *nodep = TMPFS_NODE(fn); |
assert(!dentry->lnkcnt); |
assert(!dentry->child); |
assert(!dentry->sibling); |
assert(!nodep->lnkcnt); |
assert(list_empty(&nodep->cs_head)); |
unsigned long key = dentry->index; |
hash_table_remove(&dentries, &key, 1); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = nodep->index, |
[NODES_KEY_DEV] = nodep->dev_handle |
}; |
hash_table_remove(&nodes, key, 2); |
hash_table_destroy(&dentry->names); |
if (dentry->type == TMPFS_FILE) |
free(dentry->data); |
free(dentry); |
if (nodep->type == TMPFS_FILE) |
free(nodep->data); |
free(nodep->bp); |
free(nodep); |
return EOK; |
} |
397,31 → 366,50 |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* Initialize TMPFS. */ |
if (!root && !tmpfs_init()) { |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
if (dev_handle >= 0) { |
/* Initialize TMPFS instance. */ |
if (!tmpfs_instance_init(dev_handle)) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle)); |
if (str_cmp(opts, "restore") == 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
ipc_answer_3(rid, EOK, rootp->index, rootp->size, |
rootp->lnkcnt); |
else |
ipc_answer_0(rid, ELIMIT); |
} else { |
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt); |
ipc_answer_3(rid, EOK, rootp->index, rootp->size, |
rootp->lnkcnt); |
} |
} |
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
ipc_answer_0(rid, ENOTSUP); |
libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
436,24 → 424,27 |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle, |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
/* |
* Receive the read request. |
*/ |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
460,15 → 451,16 |
} |
size_t bytes; |
if (dentry->type == TMPFS_FILE) { |
bytes = max(0, min(dentry->size - pos, len)); |
(void) ipc_data_read_finalize(callid, dentry->data + pos, |
if (nodep->type == TMPFS_FILE) { |
bytes = max(0, min(nodep->size - pos, size)); |
(void) ipc_data_read_finalize(callid, nodep->data + pos, |
bytes); |
} else { |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
int i; |
tmpfs_dentry_t *cur; |
assert(dentry->type == TMPFS_DIRECTORY); |
assert(nodep->type == TMPFS_DIRECTORY); |
/* |
* Yes, we really use O(n) algorithm here. |
475,24 → 467,21 |
* If it bothers someone, it could be fixed by introducing a |
* hash table. |
*/ |
for (i = 0, cur = dentry->child; i < pos && cur; i++, |
cur = cur->sibling) |
for (i = 0, lnk = nodep->cs_head.next; |
i < pos && lnk != &nodep->cs_head; |
i++, lnk = lnk->next) |
; |
if (!cur) { |
if (lnk == &nodep->cs_head) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
unsigned long key = (unsigned long) dentry; |
link_t *hlp = hash_table_find(&cur->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, |
link); |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
(void) ipc_data_read_finalize(callid, namep->name, |
strlen(namep->name) + 1); |
(void) ipc_data_read_finalize(callid, dentryp->name, |
str_size(dentryp->name) + 1); |
bytes = 1; |
} |
509,24 → 498,27 |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
/* |
* Receive the write request. |
*/ |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
535,13 → 527,13 |
/* |
* Check whether the file needs to grow. |
*/ |
if (pos + len <= dentry->size) { |
if (pos + size <= nodep->size) { |
/* The file size is not changing. */ |
(void) ipc_data_write_finalize(callid, dentry->data + pos, len); |
ipc_answer_2(rid, EOK, len, dentry->size); |
(void) ipc_data_write_finalize(callid, nodep->data + pos, size); |
ipc_answer_2(rid, EOK, size, nodep->size); |
return; |
} |
size_t delta = (pos + len) - dentry->size; |
size_t delta = (pos + size) - nodep->size; |
/* |
* At this point, we are deliberately extremely straightforward and |
* simply realloc the contents of the file on every write that grows the |
549,18 → 541,18 |
* our heap allocator can save us and just grow the block whenever |
* possible. |
*/ |
void *newdata = realloc(dentry->data, dentry->size + delta); |
void *newdata = realloc(nodep->data, nodep->size + delta); |
if (!newdata) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_2(rid, EOK, 0, dentry->size); |
ipc_answer_2(rid, EOK, 0, nodep->size); |
return; |
} |
/* Clear any newly allocated memory in order to emulate gaps. */ |
memset(newdata + dentry->size, 0, delta); |
dentry->size += delta; |
dentry->data = newdata; |
(void) ipc_data_write_finalize(callid, dentry->data + pos, len); |
ipc_answer_2(rid, EOK, len, dentry->size); |
memset(newdata + nodep->size, 0, delta); |
nodep->size += delta; |
nodep->data = newdata; |
(void) ipc_data_write_finalize(callid, nodep->data + pos, size); |
ipc_answer_2(rid, EOK, size, nodep->size); |
} |
void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
570,37 → 562,45 |
size_t size = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
if (size == dentry->size) { |
if (size == nodep->size) { |
ipc_answer_0(rid, EOK); |
return; |
} |
void *newdata = realloc(dentry->data, size); |
void *newdata = realloc(nodep->data, size); |
if (!newdata) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if (size > dentry->size) { |
size_t delta = size - dentry->size; |
memset(newdata + dentry->size, 0, delta); |
if (size > nodep->size) { |
size_t delta = size - nodep->size; |
memset(newdata + nodep->size, 0, delta); |
} |
dentry->size = size; |
dentry->data = newdata; |
nodep->size = size; |
nodep->data = newdata; |
ipc_answer_0(rid, EOK); |
} |
void tmpfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, EOK); |
} |
void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
608,18 → 608,37 |
int rc; |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
rc = tmpfs_destroy_node(dentry); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
rc = tmpfs_destroy_node(FS_NODE(nodep)); |
ipc_answer_0(rid, rc); |
} |
void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Dummy implementation */ |
ipc_answer_0(rid, EOK); |
} |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/fs/tmpfs/tmpfs.h |
---|
38,12 → 38,15 |
#include <atomic.h> |
#include <sys/types.h> |
#include <bool.h> |
#include <libadt/hash_table.h> |
#include <adt/hash_table.h> |
#ifndef dprintf |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
#define TMPFS_NODE(node) ((node) ? (tmpfs_node_t *)(node)->data : NULL) |
#define FS_NODE(node) ((node) ? (node)->bp : NULL) |
typedef enum { |
TMPFS_NONE, |
TMPFS_FILE, |
50,22 → 53,33 |
TMPFS_DIRECTORY |
} tmpfs_dentry_type_t; |
/* forward declaration */ |
struct tmpfs_node; |
typedef struct tmpfs_dentry { |
link_t link; /**< Linkage for the list of siblings. */ |
struct tmpfs_node *node;/**< Back pointer to TMPFS node. */ |
char *name; /**< Name of dentry. */ |
} tmpfs_dentry_t; |
typedef struct tmpfs_node { |
fs_node_t *bp; /**< Back pointer to the FS node. */ |
fs_index_t index; /**< TMPFS node index. */ |
link_t dh_link; /**< Dentries hash table link. */ |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
hash_table_t names; /**< All names linking to this TMPFS node. */ |
dev_handle_t dev_handle;/**< Device handle. */ |
link_t nh_link; /**< Nodes hash table link. */ |
tmpfs_dentry_type_t type; |
unsigned lnkcnt; /**< Link count. */ |
size_t size; /**< File size if type is TMPFS_FILE. */ |
void *data; /**< File content's if type is TMPFS_FILE. */ |
} tmpfs_dentry_t; |
link_t cs_head; /**< Head of child's siblings list. */ |
} tmpfs_node_t; |
extern fs_reg_t tmpfs_reg; |
extern libfs_ops_t tmpfs_libfs_ops; |
extern bool tmpfs_init(void); |
extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); |
72,7 → 86,11 |
extern void tmpfs_read(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_write(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_stat(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_close(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *); |
extern bool tmpfs_restore(dev_handle_t); |
/branches/arm/uspace/srv/fs/tmpfs/tmpfs.c |
---|
55,16 → 55,6 |
vfs_info_t tmpfs_vfs_info = { |
.name = "tmpfs", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNTED)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_DESTROY)] = VFS_OP_DEFINED, |
} |
}; |
fs_reg_t tmpfs_reg; |
106,27 → 96,41 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
tmpfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
tmpfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
tmpfs_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
tmpfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
tmpfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
tmpfs_truncate(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_CLOSE: |
tmpfs_close(callid, &call); |
break; |
case VFS_OUT_DESTROY: |
tmpfs_destroy(callid, &call); |
break; |
case VFS_OUT_OPEN_NODE: |
tmpfs_open_node(callid, &call); |
break; |
case VFS_OUT_STAT: |
tmpfs_stat(callid, &call); |
break; |
case VFS_OUT_SYNC: |
tmpfs_sync(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
136,24 → 140,26 |
int main(int argc, char **argv) |
{ |
int vfs_phone; |
printf(NAME ": HelenOS TMPFS file system server\n"); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
usleep(10000); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
if (!tmpfs_init()) { |
printf(NAME ": failed to initialize TMPFS\n"); |
return -1; |
} |
int rc; |
rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info, |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
return -1; |
} |
int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info, |
tmpfs_connection); |
if (rc != EOK) { |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* not reached */ |
/branches/arm/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
38,17 → 38,12 |
#include "tmpfs.h" |
#include "../../vfs/vfs.h" |
#include <ipc/ipc.h> |
#include <async.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
#include <sys/types.h> |
#include <as.h> |
#include <libfs.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <sys/mman.h> |
#include <libblock.h> |
#include <byteorder.h> |
#define TMPFS_BLOCK_SIZE 1024 |
59,19 → 54,21 |
} __attribute__((packed)); |
static bool |
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen, |
off_t *pos, tmpfs_dentry_t *parent) |
tmpfs_restore_recursion(dev_handle_t dev, off_t *bufpos, size_t *buflen, |
off_t *pos, fs_node_t *pfn) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
int rc; |
do { |
char *fname; |
tmpfs_dentry_t *node; |
fs_node_t *fn; |
tmpfs_node_t *nodep; |
uint32_t size; |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE)) |
if (block_seqread(dev, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
84,40 → 81,42 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(L_FILE); |
if (node == NULL) { |
fn = ops->create(dev, L_FILE); |
if (fn == NULL) { |
free(fname); |
return false; |
} |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
if (block_seqread(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy(fn); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
if (!ops->link((void *) parent, (void *) node, fname)) { |
ops->destroy((void *) node); |
rc = ops->link(pfn, fn, fname); |
if (rc != EOK) { |
ops->destroy(fn); |
free(fname); |
return false; |
} |
free(fname); |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
&size, sizeof(size), TMPFS_BLOCK_SIZE)) |
if (block_seqread(dev, bufpos, buflen, pos, &size, |
sizeof(size), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
size = uint32_t_le2host(size); |
node->data = malloc(size); |
if (node->data == NULL) |
nodep = TMPFS_NODE(fn); |
nodep->data = malloc(size); |
if (nodep->data == NULL) |
return false; |
node->size = size; |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
node->data, size, TMPFS_BLOCK_SIZE)) |
nodep->size = size; |
if (block_seqread(dev, bufpos, buflen, pos, nodep->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
return false; |
break; |
126,29 → 125,30 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(L_DIRECTORY); |
if (node == NULL) { |
fn = ops->create(dev, L_DIRECTORY); |
if (fn == NULL) { |
free(fname); |
return false; |
} |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
if (block_seqread(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy(fn); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
if (!ops->link((void *) parent, (void *) node, fname)) { |
ops->destroy((void *) node); |
rc = ops->link(pfn, fn, fname); |
if (rc != EOK) { |
ops->destroy(fn); |
free(fname); |
return false; |
} |
free(fname); |
if (!tmpfs_restore_recursion(phone, block, bufpos, |
buflen, pos, node)) |
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos, |
fn)) |
return false; |
break; |
163,49 → 163,34 |
bool tmpfs_restore(dev_handle_t dev) |
{ |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
int rc; |
void *block = mmap(NULL, TMPFS_BLOCK_SIZE, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
rc = block_init(dev, TMPFS_BLOCK_SIZE); |
if (rc != EOK) |
return false; |
if (block == NULL) |
return false; |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev); |
if (phone < 0) { |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
if (ipc_share_out_start(phone, block, AS_AREA_READ | AS_AREA_WRITE) != |
EOK) |
goto error; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = 0; |
char tag[6]; |
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE)) |
if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE) != EOK) |
goto error; |
tag[5] = 0; |
if (strcmp(tag, "TMPFS") != 0) |
if (str_cmp(tag, "TMPFS") != 0) |
goto error; |
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos, |
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, |
ops->root_get(dev))) |
goto error; |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
block_fini(dev); |
return true; |
error: |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
block_fini(dev); |
return false; |
} |
/branches/arm/uspace/srv/fs/tmpfs/Makefile |
---|
31,12 → 31,17 |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
56,18 → 61,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/fs/fat/fat_ops.c |
---|
36,8 → 36,11 |
*/ |
#include "fat.h" |
#include "fat_dentry.h" |
#include "fat_fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <libblock.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
45,234 → 48,26 |
#include <errno.h> |
#include <string.h> |
#include <byteorder.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <sys/mman.h> |
#include <align.h> |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) |
#define FS_NODE(node) ((node) ? (node)->bp : NULL) |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the list of cached free FAT nodes. */ |
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex); |
/** List of cached free FAT nodes. */ |
static LIST_INITIALIZE(ffn_head); |
#define FAT_NAME_LEN 8 |
#define FAT_EXT_LEN 3 |
#define FAT_PAD ' ' |
#define FAT_DENTRY_UNUSED 0x00 |
#define FAT_DENTRY_E5_ESC 0x05 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
{ |
int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) |
break; |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->name[i]; |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->ext[i]; |
} |
*buf = '\0'; |
} |
static int dev_phone = -1; /* FIXME */ |
static void *dev_buffer = NULL; /* FIXME */ |
/* TODO move somewhere else */ |
typedef struct { |
void *data; |
size_t size; |
} block_t; |
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs) |
{ |
/* FIXME */ |
block_t *b; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = offset * bs; |
assert(dev_phone != -1); |
assert(dev_buffer); |
b = malloc(sizeof(block_t)); |
if (!b) |
return NULL; |
b->data = malloc(bs); |
if (!b->data) { |
free(b); |
return NULL; |
} |
b->size = bs; |
if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos, |
b->data, bs, bs)) { |
free(b->data); |
free(b); |
return NULL; |
} |
return b; |
} |
static void block_put(block_t *block) |
{ |
/* FIXME */ |
free(block->data); |
free(block); |
} |
#define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
#define FAT_CLST_RES0 0x0000 |
#define FAT_CLST_RES1 0x0001 |
#define FAT_CLST_FIRST 0x0002 |
#define FAT_CLST_BAD 0xfff7 |
#define FAT_CLST_LAST1 0xfff8 |
#define FAT_CLST_LAST8 0xffff |
/* internally used to mark root directory's parent */ |
#define FAT_CLST_ROOTPAR FAT_CLST_RES0 |
/* internally used to mark root directory */ |
#define FAT_CLST_ROOT FAT_CLST_RES1 |
#define fat_block_get(np, off) \ |
_fat_block_get((np)->idx->dev_handle, (np)->firstc, (off)) |
static block_t * |
_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned fatcnt; |
unsigned rde; |
unsigned rds; /* root directory size */ |
unsigned sf; |
unsigned ssa; /* size of the system area */ |
unsigned clusters; |
fat_cluster_t clst = firstc; |
unsigned i; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
fatcnt = FAT_BS(bb)->fatcnt; |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); |
block_put(bb); |
rds = (sizeof(fat_dentry_t) * rde) / bps; |
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
ssa = rscnt + fatcnt * sf + rds; |
if (firstc == FAT_CLST_ROOT) { |
/* root directory special case */ |
assert(offset < rds); |
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps); |
return b; |
} |
clusters = offset / spc; |
for (i = 0; i < clusters; i++) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
assert(clst < FAT_CLST_LAST1); |
block_put(b); |
} |
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + |
offset % spc, bps); |
return b; |
} |
/** Return number of blocks allocated to a file. |
* |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster of the file. |
* |
* @return Number of blocks allocated to the file. |
*/ |
static uint16_t |
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned clusters = 0; |
fat_cluster_t clst = firstc; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
block_put(bb); |
if (firstc == FAT_CLST_RES0) { |
/* No space allocated to the file. */ |
return 0; |
} |
while (clst < FAT_CLST_LAST1) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
block_put(b); |
clusters++; |
} |
return clusters * spc; |
} |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
fibril_mutex_initialize(&node->lock); |
node->bp = NULL; |
node->idx = NULL; |
node->type = 0; |
link_initialize(&node->ffn_link); |
282,52 → 77,83 |
node->dirty = false; |
} |
static uint16_t fat_bps_get(dev_handle_t dev_handle) |
static void fat_node_sync(fat_node_t *node) |
{ |
block_t *bb; |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
uint16_t bps; |
unsigned dps; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
assert(bb != NULL); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
block_put(bb); |
assert(node->dirty); |
return bps; |
} |
bs = block_bb_get(node->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc, |
(node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); |
typedef enum { |
FAT_DENTRY_SKIP, |
FAT_DENTRY_LAST, |
FAT_DENTRY_VALID |
} fat_dentry_clsf_t; |
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); |
static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d) |
{ |
if (d->attr & FAT_ATTR_VOLLABEL) { |
/* volume label entry */ |
return FAT_DENTRY_SKIP; |
d->firstc = host2uint16_t_le(node->firstc); |
if (node->type == FAT_FILE) { |
d->size = host2uint32_t_le(node->size); |
} else if (node->type == FAT_DIRECTORY) { |
d->attr = FAT_ATTR_SUBDIR; |
} |
if (d->name[0] == FAT_DENTRY_ERASED) { |
/* not-currently-used entry */ |
return FAT_DENTRY_SKIP; |
} |
if (d->name[0] == FAT_DENTRY_UNUSED) { |
/* never used entry */ |
return FAT_DENTRY_LAST; |
} |
if (d->name[0] == FAT_DENTRY_DOT) { |
/* |
* Most likely '.' or '..'. |
* It cannot occur in a regular file name. |
*/ |
return FAT_DENTRY_SKIP; |
} |
return FAT_DENTRY_VALID; |
/* TODO: update other fields? (e.g time fields) */ |
b->dirty = true; /* need to sync block */ |
block_put(b); |
} |
static void fat_node_sync(fat_node_t *node) |
static fat_node_t *fat_node_get_new(void) |
{ |
/* TODO */ |
fs_node_t *fn; |
fat_node_t *nodep; |
fibril_mutex_lock(&ffn_mutex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
fat_idx_t *idxp_tmp; |
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); |
if (!fibril_mutex_trylock(&nodep->lock)) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (!fibril_mutex_trylock(&idxp_tmp->lock)) { |
fibril_mutex_unlock(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
fibril_mutex_unlock(&ffn_mutex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
fibril_mutex_unlock(&nodep->lock); |
fibril_mutex_unlock(&idxp_tmp->lock); |
fn = FS_NODE(nodep); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
fibril_mutex_unlock(&ffn_mutex); |
fn = (fs_node_t *)malloc(sizeof(fs_node_t)); |
if (!fn) |
return NULL; |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) { |
free(fn); |
return NULL; |
} |
} |
fat_node_initialize(nodep); |
fs_node_initialize(fn); |
fn->data = nodep; |
nodep->bp = fn; |
return nodep; |
} |
/** Internal version of fat_node_get(). |
334,12 → 160,14 |
* |
* @param idxp Locked index structure. |
*/ |
static void *fat_node_get_core(fat_idx_t *idxp) |
static fat_node_t *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
fat_node_t *nodep = NULL; |
unsigned bps; |
unsigned spc; |
unsigned dps; |
if (idxp->nodep) { |
347,10 → 175,10 |
* We are lucky. |
* The node is already instantiated in memory. |
*/ |
futex_down(&idxp->nodep->lock); |
fibril_mutex_lock(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&idxp->nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
fibril_mutex_unlock(&idxp->nodep->lock); |
return idxp->nodep; |
} |
360,41 → 188,18 |
assert(idxp->pfc); |
futex_down(&ffn_futex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
fat_idx_t *idxp_tmp; |
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); |
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) { |
futex_up(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
futex_up(&ffn_futex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) |
return NULL; |
} |
fat_node_initialize(nodep); |
nodep = fat_node_get_new(); |
if (!nodep) |
return NULL; |
bps = fat_bps_get(idxp->dev_handle); |
bs = block_bb_get(idxp->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps); |
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); |
assert(b); |
d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); |
410,7 → 215,7 |
* defined for the directory entry type. We must determine the |
* size of the directory by walking the FAT. |
*/ |
nodep->size = bps * _fat_blcks_get(idxp->dev_handle, |
nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle, |
uint16_t_le2host(d->firstc)); |
} else { |
nodep->type = FAT_FILE; |
429,10 → 234,33 |
return nodep; |
} |
/* |
* Forward declarations of FAT libfs operations. |
*/ |
static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); |
static void fat_node_put(fs_node_t *); |
static fs_node_t *fat_create_node(dev_handle_t, int); |
static int fat_destroy_node(fs_node_t *); |
static int fat_link(fs_node_t *, fs_node_t *, const char *); |
static int fat_unlink(fs_node_t *, fs_node_t *, const char *); |
static fs_node_t *fat_match(fs_node_t *, const char *); |
static fs_index_t fat_index_get(fs_node_t *); |
static size_t fat_size_get(fs_node_t *); |
static unsigned fat_lnkcnt_get(fs_node_t *); |
static bool fat_has_children(fs_node_t *); |
static fs_node_t *fat_root_get(dev_handle_t); |
static char fat_plb_get_char(unsigned); |
static bool fat_is_directory(fs_node_t *); |
static bool fat_is_file(fs_node_t *node); |
/* |
* FAT libfs operations. |
*/ |
/** Instantiate a FAT in-core node. */ |
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
void *node; |
fat_node_t *nodep; |
fat_idx_t *idxp; |
idxp = fat_idx_get_by_index(dev_handle, index); |
439,47 → 267,333 |
if (!idxp) |
return NULL; |
/* idxp->lock held */ |
node = fat_node_get_core(idxp); |
futex_up(&idxp->lock); |
return node; |
nodep = fat_node_get_core(idxp); |
fibril_mutex_unlock(&idxp->lock); |
return FS_NODE(nodep); |
} |
static void fat_node_put(void *node) |
void fat_node_put(fs_node_t *fn) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
fat_node_t *nodep = FAT_NODE(fn); |
bool destroy = false; |
futex_down(&nodep->lock); |
fibril_mutex_lock(&nodep->lock); |
if (!--nodep->refcnt) { |
futex_down(&ffn_futex); |
list_append(&nodep->ffn_link, &ffn_head); |
futex_up(&ffn_futex); |
if (nodep->idx) { |
fibril_mutex_lock(&ffn_mutex); |
list_append(&nodep->ffn_link, &ffn_head); |
fibril_mutex_unlock(&ffn_mutex); |
} 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); |
fibril_mutex_unlock(&nodep->lock); |
if (destroy) { |
free(nodep->bp); |
free(nodep); |
} |
} |
static void *fat_create(int flags) |
fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) |
{ |
return NULL; /* not supported at the moment */ |
fat_idx_t *idxp; |
fat_node_t *nodep; |
fat_bs_t *bs; |
fat_cluster_t mcl, lcl; |
uint16_t bps; |
int rc; |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
if (flags & L_DIRECTORY) { |
/* allocate a cluster */ |
rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); |
if (rc != EOK) |
return NULL; |
} |
nodep = fat_node_get_new(); |
if (!nodep) { |
fat_free_clusters(bs, dev_handle, mcl); |
return NULL; |
} |
idxp = fat_idx_get_new(dev_handle); |
if (!idxp) { |
fat_free_clusters(bs, dev_handle, mcl); |
fat_node_put(FS_NODE(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; |
fibril_mutex_unlock(&idxp->lock); |
return FS_NODE(nodep); |
} |
static int fat_destroy(void *node) |
int fat_destroy_node(fs_node_t *fn) |
{ |
return ENOTSUP; /* not supported at the moment */ |
fat_node_t *nodep = FAT_NODE(fn); |
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(fn) == false); |
bs = block_bb_get(nodep->idx->dev_handle); |
if (nodep->firstc != FAT_CLST_RES0) { |
assert(nodep->size); |
/* Free all clusters allocated to the node. */ |
fat_free_clusters(bs, nodep->idx->dev_handle, nodep->firstc); |
} |
fat_idx_destroy(nodep->idx); |
free(nodep->bp); |
free(nodep); |
return EOK; |
} |
static bool fat_link(void *prnt, void *chld, const char *name) |
int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) |
{ |
return false; /* not supported at the moment */ |
fat_node_t *parentp = FAT_NODE(pfn); |
fat_node_t *childp = FAT_NODE(cfn); |
fat_dentry_t *d; |
fat_bs_t *bs; |
block_t *b; |
int i, j; |
uint16_t bps; |
unsigned dps; |
unsigned blocks; |
fat_cluster_t mcl, lcl; |
int rc; |
fibril_mutex_lock(&childp->lock); |
if (childp->lnkcnt == 1) { |
/* |
* On FAT, we don't support multiple hard links. |
*/ |
fibril_mutex_unlock(&childp->lock); |
return EMLINK; |
} |
assert(childp->lnkcnt == 0); |
fibril_mutex_unlock(&childp->lock); |
if (!fat_dentry_name_verify(name)) { |
/* |
* Attempt to create unsupported name. |
*/ |
return ENOTSUP; |
} |
/* |
* Get us an unused parent node's dentry or grow the parent and allocate |
* a new one. |
*/ |
fibril_mutex_lock(&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); |
} |
j = 0; |
/* |
* We need to grow the parent in order to create a new unused dentry. |
*/ |
if (parentp->idx->pfc == FAT_CLST_ROOT) { |
/* Can't grow the root directory. */ |
fibril_mutex_unlock(&parentp->idx->lock); |
return ENOSPC; |
} |
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); |
if (rc != EOK) { |
fibril_mutex_unlock(&parentp->idx->lock); |
return rc; |
} |
fat_append_clusters(bs, parentp, mcl); |
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NOREAD); |
d = (fat_dentry_t *)b->data; |
/* |
* Clear all dentries in the block except for the first one (the first |
* dentry will be cleared in the next step). |
*/ |
memset(d + 1, 0, bps - sizeof(fat_dentry_t)); |
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 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); |
fibril_mutex_unlock(&parentp->idx->lock); |
fibril_mutex_lock(&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 || |
str_cmp(d->name, FAT_NAME_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
str_cpy(d->name, 8, FAT_NAME_DOT); |
str_cpy(d->ext, 3, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = host2uint16_t_le(childp->firstc); |
/* TODO: initialize also the date/time members. */ |
} |
d++; |
if (fat_classify_dentry(d) == FAT_DENTRY_LAST || |
str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
str_cpy(d->name, 8, FAT_NAME_DOT_DOT); |
str_cpy(d->ext, 3, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? |
host2uint16_t_le(FAT_CLST_RES0) : |
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; |
fibril_mutex_unlock(&childp->idx->lock); |
fibril_mutex_lock(&childp->lock); |
childp->lnkcnt = 1; |
childp->dirty = true; /* need to sync node */ |
fibril_mutex_unlock(&childp->lock); |
/* |
* Hash in the index structure into the position hash. |
*/ |
fat_idx_hashin(childp->idx); |
return EOK; |
} |
static int fat_unlink(void *prnt, void *chld) |
int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
return ENOTSUP; /* not supported at the moment */ |
fat_node_t *parentp = FAT_NODE(pfn); |
fat_node_t *childp = FAT_NODE(cfn); |
fat_bs_t *bs; |
fat_dentry_t *d; |
uint16_t bps; |
block_t *b; |
if (!parentp) |
return EBUSY; |
if (fat_has_children(cfn)) |
return ENOTEMPTY; |
fibril_mutex_lock(&parentp->lock); |
fibril_mutex_lock(&childp->lock); |
assert(childp->lnkcnt == 1); |
fibril_mutex_lock(&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; |
fibril_mutex_unlock(&childp->idx->lock); |
childp->lnkcnt = 0; |
childp->dirty = true; |
fibril_mutex_unlock(&childp->lock); |
fibril_mutex_unlock(&parentp->lock); |
return EOK; |
} |
static void *fat_match(void *prnt, const char *component) |
fs_node_t *fat_match(fs_node_t *pfn, const char *component) |
{ |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_bs_t *bs; |
fat_node_t *parentp = FAT_NODE(pfn); |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
unsigned i, j; |
unsigned bps; /* bytes per sector */ |
488,34 → 602,31 |
fat_dentry_t *d; |
block_t *b; |
futex_down(&parentp->idx->lock); |
bps = fat_bps_get(parentp->idx->dev_handle); |
fibril_mutex_lock(&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 + (parentp->size % bps != 0); |
blocks = parentp->size / bps; |
for (i = 0; i < blocks; i++) { |
unsigned dentries; |
b = fat_block_get(parentp, i); |
dentries = (i == blocks - 1) ? |
parentp->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
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_FREE: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
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; |
fat_node_t *nodep; |
/* |
* Assume tree hierarchy for locking. We |
* already have the parent and now we are going |
525,7 → 636,7 |
fat_idx_t *idx = fat_idx_get_by_pos( |
parentp->idx->dev_handle, parentp->firstc, |
i * dps + j); |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
if (!idx) { |
/* |
* Can happen if memory is low or if we |
534,39 → 645,38 |
block_put(b); |
return NULL; |
} |
node = fat_node_get_core(idx); |
futex_up(&idx->lock); |
nodep = fat_node_get_core(idx); |
fibril_mutex_unlock(&idx->lock); |
block_put(b); |
return node; |
return FS_NODE(nodep); |
} |
} |
block_put(b); |
} |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
return NULL; |
} |
static fs_index_t fat_index_get(void *node) |
fs_index_t fat_index_get(fs_node_t *fn) |
{ |
fat_node_t *fnodep = (fat_node_t *)node; |
if (!fnodep) |
return 0; |
return fnodep->idx->index; |
return FAT_NODE(fn)->idx->index; |
} |
static size_t fat_size_get(void *node) |
size_t fat_size_get(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->size; |
return FAT_NODE(fn)->size; |
} |
static unsigned fat_lnkcnt_get(void *node) |
unsigned fat_lnkcnt_get(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->lnkcnt; |
return FAT_NODE(fn)->lnkcnt; |
} |
static bool fat_has_children(void *node) |
bool fat_has_children(fs_node_t *fn) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
fat_bs_t *bs; |
fat_node_t *nodep = FAT_NODE(fn); |
unsigned bps; |
unsigned dps; |
unsigned blocks; |
575,65 → 685,63 |
if (nodep->type != FAT_DIRECTORY) |
return false; |
futex_down(&nodep->idx->lock); |
bps = fat_bps_get(nodep->idx->dev_handle); |
fibril_mutex_lock(&nodep->idx->lock); |
bs = block_bb_get(nodep->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
blocks = nodep->size / bps + (nodep->size % bps != 0); |
blocks = nodep->size / bps; |
for (i = 0; i < blocks; i++) { |
unsigned dentries; |
fat_dentry_t *d; |
b = fat_block_get(nodep, i); |
dentries = (i == blocks - 1) ? |
nodep->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
b = fat_block_get(bs, nodep, 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_FREE: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return false; |
default: |
case FAT_DENTRY_VALID: |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return true; |
} |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return true; |
} |
block_put(b); |
} |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return false; |
} |
static void *fat_root_get(dev_handle_t dev_handle) |
fs_node_t *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(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
return FAT_NODE(fn)->type == FAT_DIRECTORY; |
} |
static bool fat_is_file(void *node) |
bool fat_is_file(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->type == FAT_FILE; |
return FAT_NODE(fn)->type == FAT_FILE; |
} |
/** libfs operations */ |
641,8 → 749,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, |
655,68 → 763,103 |
.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); |
block_t *bb; |
enum cache_mode cmode; |
fat_bs_t *bs; |
uint16_t bps; |
uint16_t rde; |
int rc; |
/* |
* For now, we don't bother to remember dev_handle, dev_phone or |
* dev_buffer in some data structure. We use global variables because we |
* know there will be at most one mount on this file system. |
* Of course, this is a huge TODO item. |
*/ |
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!dev_buffer) { |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
/* Check for option enabling write through. */ |
if (str_cmp(opts, "wtcache") == 0) |
cmode = CACHE_MODE_WT; |
else |
cmode = CACHE_MODE_WB; |
if (dev_phone < 0) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, dev_phone); |
/* initialize libblock */ |
rc = block_init(dev_handle, BS_SIZE); |
if (rc != EOK) { |
ipc_answer_0(rid, rc); |
return; |
} |
rc = ipc_share_out_start(dev_phone, dev_buffer, |
AS_AREA_READ | AS_AREA_WRITE); |
/* prepare the boot block */ |
rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
/* get the buffer with the boot sector */ |
bs = block_bb_get(dev_handle); |
/* Read the number of root directory entries. */ |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
block_put(bb); |
bps = uint16_t_le2host(bs->bps); |
rde = uint16_t_le2host(bs->root_ent_max); |
if (bps != BS_SIZE) { |
munmap(dev_buffer, BS_SIZE); |
block_fini(dev_handle); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* Initialize the block cache */ |
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
rc = fat_idx_init_by_dev_handle(dev_handle); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
/* Initialize the root node. */ |
fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); |
if (!rfn) { |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fs_node_initialize(rfn); |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
munmap(dev_buffer, BS_SIZE); |
free(rfn); |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
725,8 → 868,9 |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
munmap(dev_buffer, BS_SIZE); |
free(rfn); |
free(rootp); |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
741,8 → 885,10 |
rootp->size = rde * sizeof(fat_dentry_t); |
rootp->idx = ridxp; |
ridxp->nodep = rootp; |
rootp->bp = rfn; |
rfn->data = rootp; |
futex_up(&ridxp->lock); |
fibril_mutex_unlock(&ridxp->lock); |
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); |
} |
749,7 → 895,7 |
void fat_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
762,25 → 908,31 |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
uint16_t bps = fat_bps_get(dev_handle); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
uint16_t bps; |
size_t bytes; |
block_t *b; |
if (!nodep) { |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
if (nodep->type == FAT_FILE) { |
/* |
* Our strategy for regular file reads is to read one block at |
787,11 → 939,19 |
* most and make use of the possibility to return less data than |
* requested. This keeps the code very simple. |
*/ |
bytes = min(len, bps - pos % bps); |
b = fat_block_get(nodep, pos / bps); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
if (pos >= nodep->size) { |
/* reading beyond the EOF */ |
bytes = 0; |
(void) ipc_data_read_finalize(callid, NULL, 0); |
} else { |
bytes = min(len, bps - pos % bps); |
bytes = min(bytes, nodep->size - pos); |
b = fat_block_get(bs, nodep, pos / bps, |
BLOCK_FLAGS_NONE); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} |
} else { |
unsigned bnum; |
off_t spos = pos; |
812,7 → 972,7 |
while (bnum < nodep->size / bps) { |
off_t o; |
b = fat_block_get(nodep, bnum); |
b = fat_block_get(bs, nodep, bnum, BLOCK_FLAGS_NONE); |
for (o = pos % (bps / sizeof(fat_dentry_t)); |
o < bps / sizeof(fat_dentry_t); |
o++, pos++) { |
819,6 → 979,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); |
825,7 → 986,7 |
goto miss; |
default: |
case FAT_DENTRY_VALID: |
dentry_name_canonify(d, name); |
fat_dentry_name_get(d, name); |
block_put(b); |
goto hit; |
} |
834,19 → 995,224 |
bnum++; |
} |
miss: |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
hit: |
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
(void) ipc_data_read_finalize(callid, name, str_size(name) + 1); |
bytes = (pos - spos) + 1; |
} |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
void fat_write(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); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
size_t bytes; |
block_t *b; |
uint16_t bps; |
unsigned spc; |
unsigned bpc; /* bytes per cluster */ |
off_t boundary; |
int flags = BLOCK_FLAGS_NONE; |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
fat_node_put(fn); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
/* |
* In all scenarios, we will attempt to write out only one block worth |
* of data at maximum. There might be some more efficient approaches, |
* but this one greatly simplifies fat_write(). Note that we can afford |
* to do this because the client must be ready to handle the return |
* value signalizing a smaller number of bytes written. |
*/ |
bytes = min(len, bps - pos % bps); |
if (bytes == bps) |
flags |= BLOCK_FLAGS_NOREAD; |
boundary = ROUND_UP(nodep->size, bpc); |
if (pos < boundary) { |
/* |
* This is the easier case - we are either overwriting already |
* existing contents or writing behind the EOF, but still within |
* the limits of the last cluster. The node size may grow to the |
* next block size boundary. |
*/ |
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); |
b = fat_block_get(bs, nodep, pos / bps, flags); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
if (pos + bytes > nodep->size) { |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
} |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(fn); |
return; |
} else { |
/* |
* This is the more difficult case. We must allocate new |
* clusters for the node and zero them out. |
*/ |
int status; |
unsigned nclsts; |
fat_cluster_t mcl, lcl; |
nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; |
/* create an independent chain of nclsts clusters in all FATs */ |
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); |
if (status != EOK) { |
/* could not allocate a chain of nclsts clusters */ |
fat_node_put(fn); |
ipc_answer_0(callid, status); |
ipc_answer_0(rid, status); |
return; |
} |
/* zero fill any gaps */ |
fat_fill_gap(bs, nodep, mcl, pos); |
b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc, |
flags); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
/* |
* Append the cluster chain starting in mcl to the end of the |
* node's cluster chain. |
*/ |
fat_append_clusters(bs, nodep, mcl); |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(fn); |
return; |
} |
} |
void fat_truncate(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); |
size_t size = (off_t)IPC_GET_ARG3(*request); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
uint16_t bps; |
uint8_t spc; |
unsigned bpc; /* bytes per cluster */ |
int rc; |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
if (nodep->size == size) { |
rc = EOK; |
} else if (nodep->size < size) { |
/* |
* The standard says we have the freedom to grow the node. |
* For now, we simply return an error. |
*/ |
rc = EINVAL; |
} else if (ROUND_UP(nodep->size, bpc) == ROUND_UP(size, bpc)) { |
/* |
* The node will be shrunk, but no clusters will be deallocated. |
*/ |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} else { |
/* |
* The node will be shrunk, clusters will be deallocated. |
*/ |
if (size == 0) { |
fat_chop_clusters(bs, nodep, FAT_CLST_RES0); |
} else { |
fat_cluster_t lastc; |
(void) fat_cluster_walk(bs, dev_handle, nodep->firstc, |
&lastc, (size - 1) / bpc); |
fat_chop_clusters(bs, nodep, lastc); |
} |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} |
fat_node_put(fn); |
ipc_answer_0(rid, rc); |
return; |
} |
void fat_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, EOK); |
} |
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; |
fs_node_t *fn = fat_node_get(dev_handle, index); |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
rc = fat_destroy_node(fn); |
ipc_answer_0(rid, rc); |
} |
void fat_open_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Dummy implementation */ |
ipc_answer_0(rid, EOK); |
} |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/fs/fat/fat.h |
---|
33,7 → 33,9 |
#ifndef FAT_FAT_H_ |
#define FAT_FAT_H_ |
#include "fat_fat.h" |
#include <ipc/ipc.h> |
#include <fibril_sync.h> |
#include <libfs.h> |
#include <atomic.h> |
#include <sys/types.h> |
44,7 → 46,12 |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef struct { |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
typedef struct fat_bs { |
uint8_t ji[3]; /**< Jump instruction. */ |
uint8_t oem_name[8]; |
/* BIOS Parameter Block */ |
115,34 → 122,6 |
}; |
} __attribute__ ((packed)) fat_bs_t; |
#define FAT_ATTR_RDONLY (1 << 0) |
#define FAT_ATTR_VOLLABEL (1 << 3) |
#define FAT_ATTR_SUBDIR (1 << 4) |
typedef struct { |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t reserved; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
uint16_t adate; |
union { |
uint16_t eaidx; /* FAT12/FAT16 */ |
uint16_t firstc_hi; /* FAT32 */ |
}; |
uint16_t mtime; |
uint16_t mdate; |
union { |
uint16_t firstc; /* FAT12/FAT16 */ |
uint16_t firstc_lo; /* FAT32 */ |
}; |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
typedef uint16_t fat_cluster_t; |
typedef enum { |
FAT_INVALID, |
FAT_DIRECTORY, |
182,7 → 161,7 |
/** Used indices (index) hash table link. */ |
link_t uih_link; |
futex_t lock; |
fibril_mutex_t lock; |
dev_handle_t dev_handle; |
fs_index_t index; |
/** |
200,7 → 179,10 |
/** FAT in-core node. */ |
typedef struct fat_node { |
futex_t lock; |
/** Back pointer to the FS node. */ |
fs_node_t *bp; |
fibril_mutex_t lock; |
fat_node_type_t type; |
fat_idx_t *idx; |
/** |
223,9 → 205,21 |
extern void fat_mount(ipc_callid_t, ipc_call_t *); |
extern void fat_lookup(ipc_callid_t, ipc_call_t *); |
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_stat(ipc_callid_t, ipc_call_t *); |
extern void fat_close(ipc_callid_t, ipc_call_t *); |
extern void fat_destroy(ipc_callid_t, ipc_call_t *); |
extern void fat_open_node(ipc_callid_t, ipc_call_t *); |
extern void fat_stat(ipc_callid_t, ipc_call_t *); |
extern void fat_sync(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/arm/uspace/srv/fs/fat/fat.c |
---|
49,15 → 49,6 |
vfs_info_t fat_vfs_info = { |
.name = "fat", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNTED)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
} |
}; |
fs_reg_t fat_reg; |
98,18 → 89,41 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
fat_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
fat_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
fat_read(callid, &call); |
break; |
case VFS_OUT_WRITE: |
fat_write(callid, &call); |
break; |
case VFS_OUT_TRUNCATE: |
fat_truncate(callid, &call); |
break; |
case VFS_OUT_STAT: |
fat_stat(callid, &call); |
break; |
case VFS_OUT_CLOSE: |
fat_close(callid, &call); |
break; |
case VFS_OUT_DESTROY: |
fat_destroy(callid, &call); |
break; |
case VFS_OUT_OPEN_NODE: |
fat_open_node(callid, &call); |
break; |
case VFS_OUT_SYNC: |
fat_sync(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
122,16 → 136,16 |
int vfs_phone; |
int rc; |
printf("FAT: HelenOS FAT file system server.\n"); |
printf("fat: HelenOS FAT file system server.\n"); |
rc = fat_idx_init(); |
if (rc != EOK) |
goto err; |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
usleep(10000); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf("fat: failed to connect to VFS\n"); |
return -1; |
} |
rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection); |
/branches/arm/uspace/srv/fs/fat/fat_idx.c |
---|
39,10 → 39,10 |
#include "../../vfs/vfs.h" |
#include <errno.h> |
#include <string.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.h> |
/** Each instance of this type describes one interval of freed VFS indices. */ |
typedef struct { |
68,8 → 68,8 |
link_t freed_head; |
} unused_t; |
/** Futex protecting the list of unused structures. */ |
static futex_t unused_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the list of unused structures. */ |
static FIBRIL_MUTEX_INITIALIZE(unused_lock); |
/** List of unused structures. */ |
static LIST_INITIALIZE(unused_head); |
89,7 → 89,7 |
link_t *l; |
if (lock) |
futex_down(&unused_futex); |
fibril_mutex_lock(&unused_lock); |
for (l = unused_head.next; l != &unused_head; l = l->next) { |
u = list_get_instance(l, unused_t, link); |
if (u->dev_handle == dev_handle) |
96,12 → 96,12 |
return u; |
} |
if (lock) |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return NULL; |
} |
/** Futex protecting the up_hash and ui_hash. */ |
static futex_t used_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the up_hash and ui_hash. */ |
static FIBRIL_MUTEX_INITIALIZE(used_lock); |
/** |
* Global hash table of all used fat_idx_t structures. |
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; |
231,7 → 231,7 |
*/ |
*index = u->next++; |
--u->remaining; |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return true; |
} |
} else { |
244,7 → 244,7 |
list_remove(&f->link); |
free(f); |
} |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return true; |
} |
/* |
252,7 → 252,7 |
* theoretically still possible (e.g. too many open unlinked nodes or |
* too many zero-sized nodes). |
*/ |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return false; |
} |
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; |
302,7 → 302,7 |
if (lnk->prev != &u->freed_head) |
try_coalesce_intervals(lnk->prev, lnk, |
lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
if (f->last == index - 1) { |
310,7 → 310,7 |
if (lnk->next != &u->freed_head) |
try_coalesce_intervals(lnk, lnk->next, |
lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
if (index > f->first) { |
321,7 → 321,7 |
n->first = index; |
n->last = index; |
list_insert_before(&n->link, lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
335,9 → 335,55 |
n->last = index; |
list_append(&n->link, &u->freed_head); |
} |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
} |
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
if (!fidx) |
return NULL; |
if (!fat_index_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
return NULL; |
} |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
fibril_mutex_initialize(&fidx->lock); |
fidx->dev_handle = dev_handle; |
fidx->pfc = FAT_CLST_RES0; /* no parent yet */ |
fidx->pdi = 0; |
fidx->nodep = NULL; |
return fidx; |
} |
fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
fibril_mutex_lock(&used_lock); |
fidx = fat_idx_create(dev_handle); |
if (!fidx) { |
fibril_mutex_unlock(&used_lock); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
[UIH_INDEX_KEY] = fidx->index, |
}; |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
fibril_mutex_lock(&fidx->lock); |
fibril_mutex_unlock(&used_lock); |
return fidx; |
} |
fat_idx_t * |
fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
{ |
349,21 → 395,16 |
[UPH_PDI_KEY] = pdi, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
l = hash_table_find(&up_hash, pkey); |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
} else { |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
fidx = fat_idx_create(dev_handle); |
if (!fidx) { |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
return NULL; |
} |
if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
370,23 → 411,44 |
[UIH_INDEX_KEY] = fidx->index, |
}; |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = pfc; |
fidx->pdi = pdi; |
fidx->nodep = NULL; |
hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
} |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
fibril_mutex_lock(&fidx->lock); |
fibril_mutex_unlock(&used_lock); |
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, |
}; |
fibril_mutex_lock(&used_lock); |
hash_table_insert(&up_hash, pkey, &idx->uph_link); |
fibril_mutex_unlock(&used_lock); |
} |
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, |
}; |
fibril_mutex_lock(&used_lock); |
hash_table_remove(&up_hash, pkey, 3); |
fibril_mutex_unlock(&used_lock); |
} |
fat_idx_t * |
fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index) |
{ |
397,17 → 459,44 |
[UIH_INDEX_KEY] = index, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
l = hash_table_find(&ui_hash, ikey); |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uih_link); |
futex_down(&fidx->lock); |
fibril_mutex_lock(&fidx->lock); |
} |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
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); |
fibril_mutex_lock(&used_lock); |
/* |
* 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); |
fibril_mutex_unlock(&used_lock); |
/* 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)) |
435,12 → 524,12 |
if (!u) |
return ENOMEM; |
unused_initialize(u, dev_handle); |
futex_down(&unused_futex); |
fibril_mutex_lock(&unused_lock); |
if (!unused_find(dev_handle, false)) |
list_append(&u->link, &unused_head); |
else |
rc = EEXIST; |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return rc; |
} |
451,7 → 540,7 |
u = unused_find(dev_handle, true); |
assert(u); |
list_remove(&u->link); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
while (!list_empty(&u->freed_head)) { |
freed_t *f; |
/branches/arm/uspace/srv/fs/fat/fat_fat.c |
---|
0,0 → 1,455 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file fat_fat.c |
* @brief Functions that manipulate the File Allocation Tables. |
*/ |
#include "fat_fat.h" |
#include "fat_dentry.h" |
#include "fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <libblock.h> |
#include <errno.h> |
#include <byteorder.h> |
#include <align.h> |
#include <assert.h> |
#include <fibril_sync.h> |
#include <mem.h> |
/** |
* The fat_alloc_lock mutex protects all copies of the File Allocation Table |
* during allocation of clusters. The lock does not have to be held durring |
* deallocation of clusters. |
*/ |
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); |
/** Walk the cluster chain. |
* |
* @param bs Buffer holding the boot sector for the file. |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster to start the walk with. |
* @param lastc If non-NULL, output argument hodling the last cluster number visited. |
* @param max_clusters Maximum number of clusters to visit. |
* |
* @return Number of clusters seen during the walk. |
*/ |
uint16_t |
fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, |
fat_cluster_t *lastc, uint16_t max_clusters) |
{ |
block_t *b; |
unsigned bps; |
unsigned rscnt; /* block address of the first FAT */ |
uint16_t clusters = 0; |
fat_cluster_t clst = firstc; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
if (firstc == FAT_CLST_RES0) { |
/* No space allocated to the file. */ |
if (lastc) |
*lastc = firstc; |
return 0; |
} |
while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { |
bn_t fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST); |
if (lastc) |
*lastc = clst; /* remember the last cluster number */ |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
block_put(b); |
clusters++; |
} |
if (lastc && clst < FAT_CLST_LAST1) |
*lastc = clst; |
return clusters; |
} |
/** Read block from file located on a FAT file system. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param firstc First cluster used by the file. Can be zero if the file |
* is empty. |
* @param bn Block number. |
* @param flags Flags passed to libblock. |
* |
* @return Block structure holding the requested block. |
*/ |
block_t * |
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, |
bn_t bn, int flags) |
{ |
block_t *b; |
unsigned bps; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned rde; |
unsigned rds; /* root directory size */ |
unsigned sf; |
unsigned ssa; /* size of the system area */ |
unsigned clusters, max_clusters; |
fat_cluster_t lastc; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
rde = uint16_t_le2host(bs->root_ent_max); |
sf = uint16_t_le2host(bs->sec_per_fat); |
rds = (sizeof(fat_dentry_t) * rde) / bps; |
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
ssa = rscnt + bs->fatcnt * sf + rds; |
if (firstc == FAT_CLST_ROOT) { |
/* root directory special case */ |
assert(bn < rds); |
b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags); |
return b; |
} |
max_clusters = bn / bs->spc; |
clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc, |
max_clusters); |
assert(clusters == max_clusters); |
b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc + |
bn % bs->spc, flags); |
return b; |
} |
/** Fill the gap between EOF and a new file position. |
* |
* @param bs Buffer holding the boot sector for nodep. |
* @param nodep FAT node with the gap. |
* @param mcl First cluster in an independent cluster chain that will |
* be later appended to the end of the node's own cluster |
* chain. If pos is still in the last allocated cluster, |
* this argument is ignored. |
* @param pos Position in the last node block. |
*/ |
void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos) |
{ |
uint16_t bps; |
unsigned spc; |
block_t *b; |
off_t o, boundary; |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
boundary = ROUND_UP(nodep->size, bps * spc); |
/* zero out already allocated space */ |
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; |
b = fat_block_get(bs, nodep, o / bps, flags); |
memset(b->data + o % bps, 0, bps - o % bps); |
b->dirty = true; /* need to sync node */ |
block_put(b); |
} |
if (o >= pos) |
return; |
/* zero out the initial part of the new cluster chain */ |
for (o = boundary; o < pos; o += bps) { |
b = _fat_block_get(bs, nodep->idx->dev_handle, mcl, |
(o - boundary) / bps, BLOCK_FLAGS_NOREAD); |
memset(b->data, 0, min(bps, pos - o)); |
b->dirty = true; /* need to sync node */ |
block_put(b); |
} |
} |
/** Get cluster from the first FAT. |
* |
* @param bs Buffer holding the boot sector for the file system. |
* @param dev_handle Device handle for the file system. |
* @param clst Cluster which to get. |
* |
* @return Value found in the cluster. |
*/ |
fat_cluster_t |
fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst) |
{ |
block_t *b; |
uint16_t bps; |
uint16_t rscnt; |
fat_cluster_t *cp, value; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps, |
BLOCK_FLAGS_NONE); |
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); |
value = uint16_t_le2host(*cp); |
block_put(b); |
return value; |
} |
/** Set cluster in one instance of FAT. |
* |
* @param bs Buffer holding the boot sector for the file system. |
* @param dev_handle Device handle for the file system. |
* @param fatno Number of the FAT instance where to make the change. |
* @param clst Cluster which is to be set. |
* @param value Value to set the cluster with. |
*/ |
void |
fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno, |
fat_cluster_t clst, fat_cluster_t value) |
{ |
block_t *b; |
uint16_t bps; |
uint16_t rscnt; |
uint16_t sf; |
fat_cluster_t *cp; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
sf = uint16_t_le2host(bs->sec_per_fat); |
assert(fatno < bs->fatcnt); |
b = block_get(dev_handle, rscnt + sf * fatno + |
(clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); |
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); |
*cp = host2uint16_t_le(value); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
} |
/** Replay the allocatoin of clusters in all shadow instances of FAT. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param lifo Chain of allocated clusters. |
* @param nclsts Number of clusters in the lifo chain. |
*/ |
void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle, |
fat_cluster_t *lifo, unsigned nclsts) |
{ |
uint8_t fatno; |
unsigned c; |
for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { |
for (c = 0; c < nclsts; c++) { |
fat_set_cluster(bs, dev_handle, fatno, lifo[c], |
c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); |
} |
} |
} |
/** Allocate clusters in all copies of FAT. |
* |
* This function will attempt to allocate the requested number of clusters in |
* 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). |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param nclsts Number of clusters to allocate. |
* @param mcl Output parameter where the first cluster in the chain |
* will be returned. |
* @param lcl Output parameter where the last cluster in the chain |
* will be returned. |
* |
* @return EOK on success, a negative error code otherwise. |
*/ |
int |
fat_alloc_clusters(fat_bs_t *bs, dev_handle_t dev_handle, unsigned nclsts, |
fat_cluster_t *mcl, fat_cluster_t *lcl) |
{ |
uint16_t bps; |
uint16_t rscnt; |
uint16_t sf; |
block_t *blk; |
fat_cluster_t *lifo; /* stack for storing free cluster numbers */ |
unsigned found = 0; /* top of the free cluster number stack */ |
unsigned b, c, cl; |
lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); |
if (!lifo) |
return ENOMEM; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
sf = uint16_t_le2host(bs->sec_per_fat); |
/* |
* Search FAT1 for unused clusters. |
*/ |
fibril_mutex_lock(&fat_alloc_lock); |
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) { |
/* |
* The cluster is free. Put it into our stack |
* of found clusters and mark it as non-free. |
*/ |
lifo[found] = cl; |
*clst = (found == 0) ? |
host2uint16_t_le(FAT_CLST_LAST1) : |
host2uint16_t_le(lifo[found - 1]); |
blk->dirty = true; /* need to sync block */ |
if (++found == nclsts) { |
/* we are almost done */ |
block_put(blk); |
/* update the shadow copies of FAT */ |
fat_alloc_shadow_clusters(bs, |
dev_handle, lifo, nclsts); |
*mcl = lifo[found - 1]; |
*lcl = lifo[0]; |
free(lifo); |
fibril_mutex_unlock(&fat_alloc_lock); |
return EOK; |
} |
} |
} |
block_put(blk); |
} |
fibril_mutex_unlock(&fat_alloc_lock); |
/* |
* We could not find enough clusters. Now we need to free the clusters |
* we have allocated so far. |
*/ |
while (found--) { |
fat_set_cluster(bs, dev_handle, FAT1, lifo[found], |
FAT_CLST_RES0); |
} |
free(lifo); |
return ENOSPC; |
} |
/** Free clusters forming a cluster chain in all copies of FAT. |
* |
* @param bs Buffer hodling the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param firstc First cluster in the chain which is to be freed. |
*/ |
void |
fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
unsigned fatno; |
fat_cluster_t nextc; |
/* 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); |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, dev_handle, fatno, firstc, |
FAT_CLST_RES0); |
firstc = nextc; |
} |
} |
/** Append a cluster chain to the last file cluster in all FATs. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param nodep Node representing the file. |
* @param mcl First cluster of the cluster chain to append. |
*/ |
void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) |
{ |
dev_handle_t dev_handle = nodep->idx->dev_handle; |
fat_cluster_t lcl; |
uint8_t fatno; |
if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, |
(uint16_t) -1) == 0) { |
/* No clusters allocated to the node yet. */ |
nodep->firstc = mcl; |
nodep->dirty = true; /* need to sync node */ |
return; |
} |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl); |
} |
/** Chop off node clusters in all copies of FAT. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param nodep FAT node where the chopping will take place. |
* @param lastc Last cluster which will remain in the node. If this |
* argument is FAT_CLST_RES0, then all clusters will |
* be chopped off. |
*/ |
void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) |
{ |
dev_handle_t dev_handle = nodep->idx->dev_handle; |
if (lastc == FAT_CLST_RES0) { |
/* The node will have zero size and no clusters allocated. */ |
fat_free_clusters(bs, dev_handle, nodep->firstc); |
nodep->firstc = FAT_CLST_RES0; |
nodep->dirty = true; /* need to sync node */ |
} else { |
fat_cluster_t nextc; |
unsigned fatno; |
nextc = fat_get_cluster(bs, dev_handle, lastc); |
/* Terminate the cluster chain in all copies of FAT. */ |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1); |
/* Free all following clusters. */ |
fat_free_clusters(bs, dev_handle, nextc); |
} |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/fat/Makefile |
---|
31,12 → 31,17 |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
45,7 → 50,9 |
SOURCES = \ |
fat.c \ |
fat_ops.c \ |
fat_idx.c |
fat_idx.c \ |
fat_dentry.c \ |
fat_fat.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
56,18 → 63,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/fs/fat/fat_dentry.c |
---|
0,0 → 1,243 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file fat_dentry.c |
* @brief Functions that work with FAT directory entries. |
*/ |
#include "fat_dentry.h" |
#include <ctype.h> |
#include <string.h> |
static bool is_d_char(const char ch) |
{ |
if (isalnum(ch) || ch == '_') |
return true; |
else |
return false; |
} |
/** 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; |
size_t size; |
if (!(rc = stricmp(name, component))) |
return rc; |
if (!str_chr(name, '.')) { |
/* |
* There is no '.' in the name, so we know that there is enough |
* space for appending an extra '.' to name. |
*/ |
size = str_size(name); |
name[size] = '.'; |
name[size + 1] = '\0'; |
rc = stricmp(name, component); |
} |
return rc; |
} |
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) |
{ |
unsigned int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) |
break; |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else { |
if (d->lcase & FAT_LCASE_LOWER_NAME) |
*buf++ = tolower(d->name[i]); |
else |
*buf++ = d->name[i]; |
} |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else { |
if (d->lcase & FAT_LCASE_LOWER_EXT) |
*buf++ = tolower(d->ext[i]); |
else |
*buf++ = d->ext[i]; |
} |
} |
*buf = '\0'; |
} |
void fat_dentry_name_set(fat_dentry_t *d, const char *name) |
{ |
unsigned int i; |
const char fake_ext[] = " "; |
bool lower_name = true; |
bool lower_ext = true; |
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: |
if (isalpha(*name)) { |
if (!islower(*name)) |
lower_name = false; |
} |
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: |
if (isalpha(*name)) { |
if (!islower(*name)) |
lower_ext = false; |
} |
d->ext[i] = toupper(*name++); |
break; |
} |
} |
if (lower_name) |
d->lcase |= FAT_LCASE_LOWER_NAME; |
else |
d->lcase &= ~FAT_LCASE_LOWER_NAME; |
if (lower_ext) |
d->lcase |= FAT_LCASE_LOWER_EXT; |
else |
d->lcase &= ~FAT_LCASE_LOWER_EXT; |
} |
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; |
} |
if (d->name[0] == FAT_DENTRY_ERASED) { |
/* not-currently-used entry */ |
return FAT_DENTRY_FREE; |
} |
if (d->name[0] == FAT_DENTRY_UNUSED) { |
/* never used entry */ |
return FAT_DENTRY_LAST; |
} |
if (d->name[0] == FAT_DENTRY_DOT) { |
/* |
* Most likely '.' or '..'. |
* It cannot occur in a regular file name. |
*/ |
return FAT_DENTRY_SKIP; |
} |
return FAT_DENTRY_VALID; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/fs/fat/fat_dentry.h |
---|
0,0 → 1,99 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef FAT_FAT_DENTRY_H_ |
#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_LCASE_LOWER_NAME 0x08 |
#define FAT_LCASE_LOWER_EXT 0x10 |
#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; |
typedef struct { |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t lcase; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
uint16_t adate; |
union { |
uint16_t eaidx; /* FAT12/FAT16 */ |
uint16_t firstc_hi; /* FAT32 */ |
} __attribute__ ((packed)); |
uint16_t mtime; |
uint16_t mdate; |
union { |
uint16_t firstc; /* FAT12/FAT16 */ |
uint16_t firstc_lo; /* FAT32 */ |
} __attribute__ ((packed)); |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
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/arm/uspace/srv/fs/fat/fat_fat.h |
---|
0,0 → 1,91 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef FAT_FAT_FAT_H_ |
#define FAT_FAT_FAT_H_ |
#include "../../vfs/vfs.h" |
#include <stdint.h> |
#include <libblock.h> |
#define FAT1 0 |
#define FAT_CLST_RES0 0x0000 |
#define FAT_CLST_RES1 0x0001 |
#define FAT_CLST_FIRST 0x0002 |
#define FAT_CLST_BAD 0xfff7 |
#define FAT_CLST_LAST1 0xfff8 |
#define FAT_CLST_LAST8 0xffff |
/* internally used to mark root directory's parent */ |
#define FAT_CLST_ROOTPAR FAT_CLST_RES0 |
/* internally used to mark root directory */ |
#define FAT_CLST_ROOT FAT_CLST_RES1 |
/* forward declarations */ |
struct block; |
struct fat_node; |
struct fat_bs; |
typedef uint16_t fat_cluster_t; |
#define fat_clusters_get(bs, dh, fc) \ |
fat_cluster_walk((bs), (dh), (fc), NULL, (uint16_t) -1) |
extern uint16_t fat_cluster_walk(struct fat_bs *, dev_handle_t, fat_cluster_t, |
fat_cluster_t *, uint16_t); |
#define fat_block_get(bs, np, bn, flags) \ |
_fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (bn), (flags)) |
extern struct block *_fat_block_get(struct fat_bs *, dev_handle_t, |
fat_cluster_t, bn_t, int); |
extern void fat_append_clusters(struct fat_bs *, struct fat_node *, |
fat_cluster_t); |
extern void fat_chop_clusters(struct fat_bs *, struct fat_node *, |
fat_cluster_t); |
extern int fat_alloc_clusters(struct fat_bs *, dev_handle_t, unsigned, |
fat_cluster_t *, fat_cluster_t *); |
extern void fat_free_clusters(struct fat_bs *, dev_handle_t, fat_cluster_t); |
extern void fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t, |
fat_cluster_t *, unsigned); |
extern fat_cluster_t fat_get_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t); |
extern void fat_set_cluster(struct fat_bs *, dev_handle_t, unsigned, |
fat_cluster_t, fat_cluster_t); |
extern void fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t, |
off_t); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/arch/ppc32/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ppc32/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/amd64 |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/arm/uspace/srv/kbd/arch/ppc64/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ppc64/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/mips32/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/mips32/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia32/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia32/include/scanc.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia32/src/scanc.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia32/src/mouse.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia32/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/sparc64/include/scanc.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/sparc64/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/sparc64/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/sparc64/src/scanc.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia64/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/ia64/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/include/pl050.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/include/scanc.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/src/kbd_gxemul.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/src/scanc.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/src/kbd_icp.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/arm32/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/arch/mips32eb |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/arm/uspace/srv/kbd/ctl/pc.c |
---|
0,0 → 1,234 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief PC keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
enum dec_state { |
ds_s, |
ds_e |
}; |
static enum dec_state ds; |
static int scanmap_simple[] = { |
[0x29] = KC_BACKTICK, |
[0x02] = KC_1, |
[0x03] = KC_2, |
[0x04] = KC_3, |
[0x05] = KC_4, |
[0x06] = KC_5, |
[0x07] = KC_6, |
[0x08] = KC_7, |
[0x09] = KC_8, |
[0x0a] = KC_9, |
[0x0b] = KC_0, |
[0x0c] = KC_MINUS, |
[0x0d] = KC_EQUALS, |
[0x0e] = KC_BACKSPACE, |
[0x0f] = KC_TAB, |
[0x10] = KC_Q, |
[0x11] = KC_W, |
[0x12] = KC_E, |
[0x13] = KC_R, |
[0x14] = KC_T, |
[0x15] = KC_Y, |
[0x16] = KC_U, |
[0x17] = KC_I, |
[0x18] = KC_O, |
[0x19] = KC_P, |
[0x1a] = KC_LBRACKET, |
[0x1b] = KC_RBRACKET, |
[0x3a] = KC_CAPS_LOCK, |
[0x1e] = KC_A, |
[0x1f] = KC_S, |
[0x20] = KC_D, |
[0x21] = KC_F, |
[0x22] = KC_G, |
[0x23] = KC_H, |
[0x24] = KC_J, |
[0x25] = KC_K, |
[0x26] = KC_L, |
[0x27] = KC_SEMICOLON, |
[0x28] = KC_QUOTE, |
[0x2b] = KC_BACKSLASH, |
[0x2a] = KC_LSHIFT, |
[0x2c] = KC_Z, |
[0x2d] = KC_X, |
[0x2e] = KC_C, |
[0x2f] = KC_V, |
[0x30] = KC_B, |
[0x31] = KC_N, |
[0x32] = KC_M, |
[0x33] = KC_COMMA, |
[0x34] = KC_PERIOD, |
[0x35] = KC_SLASH, |
[0x36] = KC_RSHIFT, |
[0x1d] = KC_LCTRL, |
[0x38] = KC_LALT, |
[0x39] = KC_SPACE, |
[0x01] = KC_ESCAPE, |
[0x3b] = KC_F1, |
[0x3c] = KC_F2, |
[0x3d] = KC_F3, |
[0x3e] = KC_F4, |
[0x3f] = KC_F5, |
[0x40] = KC_F6, |
[0x41] = KC_F7, |
[0x42] = KC_F8, |
[0x43] = KC_F9, |
[0x44] = KC_F10, |
[0x57] = KC_F11, |
[0x58] = KC_F12, |
[0x46] = KC_SCROLL_LOCK, |
[0x1c] = KC_ENTER, |
[0x45] = KC_NUM_LOCK, |
[0x37] = KC_NTIMES, |
[0x4a] = KC_NMINUS, |
[0x4e] = KC_NPLUS, |
[0x47] = KC_N7, |
[0x48] = KC_N8, |
[0x49] = KC_N9, |
[0x4b] = KC_N4, |
[0x4c] = KC_N5, |
[0x4d] = KC_N6, |
[0x4f] = KC_N1, |
[0x50] = KC_N2, |
[0x51] = KC_N3, |
[0x52] = KC_N0, |
[0x53] = KC_NPERIOD |
}; |
static int scanmap_e0[] = { |
[0x38] = KC_RALT, |
[0x1d] = KC_RSHIFT, |
[0x37] = KC_PRTSCR, |
[0x52] = KC_INSERT, |
[0x47] = KC_HOME, |
[0x49] = KC_PAGE_UP, |
[0x53] = KC_DELETE, |
[0x4f] = KC_END, |
[0x51] = KC_PAGE_DOWN, |
[0x48] = KC_UP, |
[0x4b] = KC_LEFT, |
[0x50] = KC_DOWN, |
[0x4d] = KC_RIGHT, |
[0x35] = KC_NSLASH, |
[0x1c] = KC_NENTER |
}; |
int kbd_ctl_init(void) |
{ |
ds = ds_s; |
return 0; |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
console_ev_type_t type; |
unsigned int key; |
int *map; |
size_t map_length; |
if (scancode == 0xe0) { |
ds = ds_e; |
return; |
} |
switch (ds) { |
case ds_s: |
map = scanmap_simple; |
map_length = sizeof(scanmap_simple) / sizeof(int); |
break; |
case ds_e: |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
default: |
map = NULL; |
map_length = 0; |
} |
ds = ds_s; |
if (scancode & 0x80) { |
scancode &= ~0x80; |
type = KEY_RELEASE; |
} else { |
type = KEY_PRESS; |
} |
if ((scancode < 0) || ((size_t) scancode >= map_length)) |
return; |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/ctl/stty.c |
---|
0,0 → 1,228 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Serial TTY-like keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <io/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
#include <stroke.h> |
/** Scancode parser */ |
static gsp_t sp; |
/** Current parser state */ |
static int ds; |
#include <stdio.h> |
int seq_defs[] = { |
/* Not shifted */ |
0, KC_BACKTICK, 0x60, GSP_END, |
0, KC_1, 0x31, GSP_END, |
0, KC_2, 0x32, GSP_END, |
0, KC_3, 0x33, GSP_END, |
0, KC_4, 0x34, GSP_END, |
0, KC_5, 0x35, GSP_END, |
0, KC_6, 0x36, GSP_END, |
0, KC_7, 0x37, GSP_END, |
0, KC_8, 0x38, GSP_END, |
0, KC_9, 0x39, GSP_END, |
0, KC_0, 0x30, GSP_END, |
0, KC_MINUS, 0x2d, GSP_END, |
0, KC_EQUALS, 0x3d, GSP_END, |
0, KC_BACKSPACE, 0x08, GSP_END, |
0, KC_TAB, 0x09, GSP_END, |
0, KC_Q, 0x71, GSP_END, |
0, KC_W, 0x77, GSP_END, |
0, KC_E, 0x65, GSP_END, |
0, KC_R, 0x72, GSP_END, |
0, KC_T, 0x74, GSP_END, |
0, KC_Y, 0x79, GSP_END, |
0, KC_U, 0x75, GSP_END, |
0, KC_I, 0x69, GSP_END, |
0, KC_O, 0x6f, GSP_END, |
0, KC_P, 0x70, GSP_END, |
0, KC_LBRACKET, 0x5b, GSP_END, |
0, KC_RBRACKET, 0x5d, GSP_END, |
0, KC_A, 0x61, GSP_END, |
0, KC_S, 0x73, GSP_END, |
0, KC_D, 0x64, GSP_END, |
0, KC_F, 0x66, GSP_END, |
0, KC_G, 0x67, GSP_END, |
0, KC_H, 0x68, GSP_END, |
0, KC_J, 0x6a, GSP_END, |
0, KC_K, 0x6b, GSP_END, |
0, KC_L, 0x6c, GSP_END, |
0, KC_SEMICOLON, 0x3b, GSP_END, |
0, KC_QUOTE, 0x27, GSP_END, |
0, KC_BACKSLASH, 0x5c, GSP_END, |
0, KC_Z, 0x7a, GSP_END, |
0, KC_X, 0x78, GSP_END, |
0, KC_C, 0x63, GSP_END, |
0, KC_V, 0x76, GSP_END, |
0, KC_B, 0x62, GSP_END, |
0, KC_N, 0x6e, GSP_END, |
0, KC_M, 0x6d, GSP_END, |
0, KC_COMMA, 0x2c, GSP_END, |
0, KC_PERIOD, 0x2e, GSP_END, |
0, KC_SLASH, 0x2f, GSP_END, |
/* Shifted */ |
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END, |
KM_SHIFT, KC_1, 0x21, GSP_END, |
KM_SHIFT, KC_2, 0x40, GSP_END, |
KM_SHIFT, KC_3, 0x23, GSP_END, |
KM_SHIFT, KC_4, 0x24, GSP_END, |
KM_SHIFT, KC_5, 0x25, GSP_END, |
KM_SHIFT, KC_6, 0x5e, GSP_END, |
KM_SHIFT, KC_7, 0x26, GSP_END, |
KM_SHIFT, KC_8, 0x2a, GSP_END, |
KM_SHIFT, KC_9, 0x28, GSP_END, |
KM_SHIFT, KC_0, 0x29, GSP_END, |
KM_SHIFT, KC_MINUS, 0x5f, GSP_END, |
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END, |
KM_SHIFT, KC_Q, 0x51, GSP_END, |
KM_SHIFT, KC_W, 0x57, GSP_END, |
KM_SHIFT, KC_E, 0x45, GSP_END, |
KM_SHIFT, KC_R, 0x52, GSP_END, |
KM_SHIFT, KC_T, 0x54, GSP_END, |
KM_SHIFT, KC_Y, 0x59, GSP_END, |
KM_SHIFT, KC_U, 0x55, GSP_END, |
KM_SHIFT, KC_I, 0x49, GSP_END, |
KM_SHIFT, KC_O, 0x4f, GSP_END, |
KM_SHIFT, KC_P, 0x50, GSP_END, |
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END, |
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END, |
KM_SHIFT, KC_A, 0x41, GSP_END, |
KM_SHIFT, KC_S, 0x53, GSP_END, |
KM_SHIFT, KC_D, 0x44, GSP_END, |
KM_SHIFT, KC_F, 0x46, GSP_END, |
KM_SHIFT, KC_G, 0x47, GSP_END, |
KM_SHIFT, KC_H, 0x48, GSP_END, |
KM_SHIFT, KC_J, 0x4a, GSP_END, |
KM_SHIFT, KC_K, 0x4b, GSP_END, |
KM_SHIFT, KC_L, 0x4c, GSP_END, |
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END, |
KM_SHIFT, KC_QUOTE, 0x22, GSP_END, |
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END, |
KM_SHIFT, KC_Z, 0x5a, GSP_END, |
KM_SHIFT, KC_X, 0x58, GSP_END, |
KM_SHIFT, KC_C, 0x43, GSP_END, |
KM_SHIFT, KC_V, 0x56, GSP_END, |
KM_SHIFT, KC_B, 0x42, GSP_END, |
KM_SHIFT, KC_N, 0x4e, GSP_END, |
KM_SHIFT, KC_M, 0x4d, GSP_END, |
KM_SHIFT, KC_COMMA, 0x3c, GSP_END, |
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END, |
KM_SHIFT, KC_SLASH, 0x3f, GSP_END, |
/* ... */ |
0, KC_SPACE, 0x20, GSP_END, |
0, KC_ENTER, 0x0a, GSP_END, |
0, KC_ENTER, 0x0d, GSP_END, |
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END, |
0, KC_F1, 0x1b, 0x4f, 0x50, GSP_END, |
0, KC_F2, 0x1b, 0x4f, 0x51, GSP_END, |
0, KC_F3, 0x1b, 0x4f, 0x52, GSP_END, |
0, KC_F4, 0x1b, 0x4f, 0x53, GSP_END, |
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END, |
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END, |
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END, |
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END, |
0, KC_F9, 0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END, |
0, KC_F10, 0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END, |
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END, |
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END, |
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END, |
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END, |
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END, |
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END, |
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END, |
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END, |
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END, |
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END, |
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END, |
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, |
0, 0 |
}; |
int kbd_ctl_init(void) |
{ |
ds = 0; |
gsp_init(&sp); |
return gsp_insert_defs(&sp, seq_defs); |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
unsigned mods, key; |
ds = gsp_step(&sp, ds, scancode, &mods, &key); |
if (key != 0) { |
stroke_sim(mods, key); |
} |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/ctl/sun.c |
---|
0,0 → 1,209 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Sun keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <kbd_ctl.h> |
#define KBD_KEY_RELEASE 0x80 |
#define KBD_ALL_KEYS_UP 0x7f |
static int scanmap_simple[]; |
int kbd_ctl_init(void) |
{ |
return 0; |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
console_ev_type_t type; |
unsigned int key; |
if (scancode < 0 || scancode >= 0x100) |
return; |
if (scancode == KBD_ALL_KEYS_UP) |
return; |
if (scancode & KBD_KEY_RELEASE) { |
scancode &= ~KBD_KEY_RELEASE; |
type = KEY_RELEASE; |
} else { |
type = KEY_PRESS; |
} |
key = scanmap_simple[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
/** Primary meaning of scancodes. */ |
static int scanmap_simple[] = { |
[0x00] = 0, |
[0x01] = 0, |
[0x02] = 0, |
[0x03] = 0, |
[0x04] = 0, |
[0x05] = KC_F1, |
[0x06] = KC_F2, |
[0x07] = KC_F10, |
[0x08] = KC_F3, |
[0x09] = KC_F11, |
[0x0a] = KC_F4, |
[0x0b] = KC_F12, |
[0x0c] = KC_F5, |
[0x0d] = KC_RALT, |
[0x0e] = KC_F6, |
[0x0f] = 0, |
[0x10] = KC_F7, |
[0x11] = KC_F8, |
[0x12] = KC_F9, |
[0x13] = KC_LALT, |
[0x14] = KC_UP, |
[0x15] = KC_PAUSE, |
[0x16] = 0, |
[0x17] = KC_SCROLL_LOCK, |
[0x18] = KC_LEFT, |
[0x19] = 0, |
[0x1a] = 0, |
[0x1b] = KC_DOWN, |
[0x1c] = KC_RIGHT, |
[0x1d] = KC_ESCAPE, |
[0x1e] = KC_1, |
[0x1f] = KC_2, |
[0x20] = KC_3, |
[0x21] = KC_4, |
[0x22] = KC_5, |
[0x23] = KC_6, |
[0x24] = KC_7, |
[0x25] = KC_8, |
[0x26] = KC_9, |
[0x27] = KC_0, |
[0x28] = KC_MINUS, |
[0x29] = KC_EQUALS, |
[0x2a] = KC_BACKTICK, |
[0x2b] = KC_BACKSPACE, |
[0x2c] = KC_INSERT, |
[0x2d] = 0, |
[0x2e] = KC_NSLASH, |
[0x2f] = KC_NTIMES, |
[0x30] = 0, |
[0x31] = 0, |
[0x32] = KC_NPERIOD, |
[0x33] = 0, |
[0x34] = KC_HOME, |
[0x35] = KC_TAB, |
[0x36] = KC_Q, |
[0x37] = KC_W, |
[0x38] = KC_E, |
[0x39] = KC_R, |
[0x3a] = KC_T, |
[0x3b] = KC_Y, |
[0x3c] = KC_U, |
[0x3d] = KC_I, |
[0x3e] = KC_O, |
[0x3f] = KC_P, |
[0x40] = KC_LBRACKET, |
[0x41] = KC_RBRACKET, |
[0x42] = KC_DELETE, |
[0x43] = 0, |
[0x44] = KC_N7, |
[0x45] = KC_N8, |
[0x46] = KC_N9, |
[0x47] = KC_NMINUS, |
[0x48] = 0, |
[0x49] = 0, |
[0x4a] = KC_END, |
[0x4b] = 0, |
[0x4c] = KC_LCTRL, |
[0x4d] = KC_A, |
[0x4e] = KC_S, |
[0x4f] = KC_D, |
[0x50] = KC_F, |
[0x51] = KC_G, |
[0x52] = KC_H, |
[0x53] = KC_J, |
[0x54] = KC_K, |
[0x55] = KC_L, |
[0x56] = KC_SEMICOLON, |
[0x57] = KC_QUOTE, |
[0x58] = KC_BACKSLASH, |
[0x59] = KC_ENTER, |
[0x5a] = KC_NENTER, |
[0x5b] = KC_N4, |
[0x5c] = KC_N5, |
[0x5d] = KC_N6, |
[0x5e] = KC_N0, |
[0x5f] = 0, |
[0x60] = KC_PAGE_UP, |
[0x61] = 0, |
[0x62] = KC_NUM_LOCK, |
[0x63] = KC_LSHIFT, |
[0x64] = KC_Z, |
[0x65] = KC_X, |
[0x66] = KC_C, |
[0x67] = KC_V, |
[0x68] = KC_B, |
[0x69] = KC_N, |
[0x6a] = KC_M, |
[0x6b] = KC_COMMA, |
[0x6c] = KC_PERIOD, |
[0x6d] = KC_SLASH, |
[0x6e] = KC_RSHIFT, |
[0x6f] = 0, |
[0x70] = KC_N1, |
[0x71] = KC_N2, |
[0x72] = KC_N3, |
[0x73] = 0, |
[0x74] = 0, |
[0x75] = 0, |
[0x76] = 0, |
[0x77] = KC_CAPS_LOCK, |
[0x78] = 0, |
[0x79] = KC_SPACE, |
[0x7a] = 0, |
[0x7b] = KC_PAGE_DOWN, |
[0x7c] = 0, |
[0x7d] = KC_NPLUS, |
[0x7e] = 0, |
[0x7f] = 0 |
}; |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/ctl/gxe_fb.c |
---|
0,0 → 1,229 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief GXEmul framebuffer-mode keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
#include <stroke.h> |
/** Scancode parser */ |
static gsp_t sp; |
/** Current parser state */ |
static int ds; |
#include <stdio.h> |
int seq_defs[] = { |
/* Not shifted */ |
0, KC_BACKTICK, 0x60, GSP_END, |
0, KC_1, 0x31, GSP_END, |
0, KC_2, 0x32, GSP_END, |
0, KC_3, 0x33, GSP_END, |
0, KC_4, 0x34, GSP_END, |
0, KC_5, 0x35, GSP_END, |
0, KC_6, 0x36, GSP_END, |
0, KC_7, 0x37, GSP_END, |
0, KC_8, 0x38, GSP_END, |
0, KC_9, 0x39, GSP_END, |
0, KC_0, 0x30, GSP_END, |
0, KC_MINUS, 0x2d, GSP_END, |
0, KC_EQUALS, 0x3d, GSP_END, |
0, KC_BACKSPACE, 0x08, GSP_END, |
0, KC_TAB, 0x09, GSP_END, |
0, KC_Q, 0x71, GSP_END, |
0, KC_W, 0x77, GSP_END, |
0, KC_E, 0x65, GSP_END, |
0, KC_R, 0x72, GSP_END, |
0, KC_T, 0x74, GSP_END, |
0, KC_Y, 0x79, GSP_END, |
0, KC_U, 0x75, GSP_END, |
0, KC_I, 0x69, GSP_END, |
0, KC_O, 0x6f, GSP_END, |
0, KC_P, 0x70, GSP_END, |
0, KC_LBRACKET, 0x5b, GSP_END, |
0, KC_RBRACKET, 0x5d, GSP_END, |
0, KC_A, 0x61, GSP_END, |
0, KC_S, 0x73, GSP_END, |
0, KC_D, 0x64, GSP_END, |
0, KC_F, 0x66, GSP_END, |
0, KC_G, 0x67, GSP_END, |
0, KC_H, 0x68, GSP_END, |
0, KC_J, 0x6a, GSP_END, |
0, KC_K, 0x6b, GSP_END, |
0, KC_L, 0x6c, GSP_END, |
0, KC_SEMICOLON, 0x3b, GSP_END, |
0, KC_QUOTE, 0x27, GSP_END, |
0, KC_BACKSLASH, 0x5c, GSP_END, |
0, KC_Z, 0x7a, GSP_END, |
0, KC_X, 0x78, GSP_END, |
0, KC_C, 0x63, GSP_END, |
0, KC_V, 0x76, GSP_END, |
0, KC_B, 0x62, GSP_END, |
0, KC_N, 0x6e, GSP_END, |
0, KC_M, 0x6d, GSP_END, |
0, KC_COMMA, 0x2c, GSP_END, |
0, KC_PERIOD, 0x2e, GSP_END, |
0, KC_SLASH, 0x2f, GSP_END, |
/* Shifted */ |
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END, |
KM_SHIFT, KC_1, 0x21, GSP_END, |
KM_SHIFT, KC_2, 0x40, GSP_END, |
KM_SHIFT, KC_3, 0x23, GSP_END, |
KM_SHIFT, KC_4, 0x24, GSP_END, |
KM_SHIFT, KC_5, 0x25, GSP_END, |
KM_SHIFT, KC_6, 0x5e, GSP_END, |
KM_SHIFT, KC_7, 0x26, GSP_END, |
KM_SHIFT, KC_8, 0x2a, GSP_END, |
KM_SHIFT, KC_9, 0x28, GSP_END, |
KM_SHIFT, KC_0, 0x29, GSP_END, |
KM_SHIFT, KC_MINUS, 0x5f, GSP_END, |
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END, |
KM_SHIFT, KC_Q, 0x51, GSP_END, |
KM_SHIFT, KC_W, 0x57, GSP_END, |
KM_SHIFT, KC_E, 0x45, GSP_END, |
KM_SHIFT, KC_R, 0x52, GSP_END, |
KM_SHIFT, KC_T, 0x54, GSP_END, |
KM_SHIFT, KC_Y, 0x59, GSP_END, |
KM_SHIFT, KC_U, 0x55, GSP_END, |
KM_SHIFT, KC_I, 0x49, GSP_END, |
KM_SHIFT, KC_O, 0x4f, GSP_END, |
KM_SHIFT, KC_P, 0x50, GSP_END, |
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END, |
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END, |
KM_SHIFT, KC_A, 0x41, GSP_END, |
KM_SHIFT, KC_S, 0x53, GSP_END, |
KM_SHIFT, KC_D, 0x44, GSP_END, |
KM_SHIFT, KC_F, 0x46, GSP_END, |
KM_SHIFT, KC_G, 0x47, GSP_END, |
KM_SHIFT, KC_H, 0x48, GSP_END, |
KM_SHIFT, KC_J, 0x4a, GSP_END, |
KM_SHIFT, KC_K, 0x4b, GSP_END, |
KM_SHIFT, KC_L, 0x4c, GSP_END, |
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END, |
KM_SHIFT, KC_QUOTE, 0x22, GSP_END, |
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END, |
KM_SHIFT, KC_Z, 0x5a, GSP_END, |
KM_SHIFT, KC_X, 0x58, GSP_END, |
KM_SHIFT, KC_C, 0x43, GSP_END, |
KM_SHIFT, KC_V, 0x56, GSP_END, |
KM_SHIFT, KC_B, 0x42, GSP_END, |
KM_SHIFT, KC_N, 0x4e, GSP_END, |
KM_SHIFT, KC_M, 0x4d, GSP_END, |
KM_SHIFT, KC_COMMA, 0x3c, GSP_END, |
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END, |
KM_SHIFT, KC_SLASH, 0x3f, GSP_END, |
/* ... */ |
0, KC_SPACE, 0x20, GSP_END, |
0, KC_ENTER, 0x0a, GSP_END, |
0, KC_ENTER, 0x0d, GSP_END, |
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END, |
0, KC_F1, 0x1b, 0x5b, 0x4f, 0x50, GSP_END, |
0, KC_F2, 0x1b, 0x5b, 0x4f, 0x51, GSP_END, |
0, KC_F3, 0x1b, 0x5b, 0x4f, 0x52, GSP_END, |
0, KC_F4, 0x1b, 0x5b, 0x4f, 0x53, GSP_END, |
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, GSP_END, |
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, GSP_END, |
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, GSP_END, |
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, GSP_END, |
0, KC_F9, 0x1b, 0x5b, 0x32, 0x38, GSP_END, |
0, KC_F10, 0x1b, 0x5b, 0x32, 0x39, GSP_END, |
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, GSP_END, |
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, GSP_END, |
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END, |
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END, |
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END, |
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END, |
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END, |
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END, |
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END, |
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END, |
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END, |
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, |
0, 0 |
}; |
int kbd_ctl_init(void) |
{ |
ds = 0; |
gsp_init(&sp); |
return gsp_insert_defs(&sp, seq_defs); |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
unsigned mods, key; |
ds = gsp_step(&sp, ds, scancode, &mods, &key); |
if (key != 0) { |
stroke_sim(mods, key); |
} |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/port/i8042.c |
---|
0,0 → 1,177 |
/* |
* 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 kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief i8042 port driver. |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <unistd.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
#include <ddi.h> |
#include "i8042.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 |
static irq_cmd_t i8042_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = i8042_OUTPUT_FULL, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
static irq_code_t i8042_kbd = { |
sizeof(i8042_cmds) / sizeof(irq_cmd_t), |
i8042_cmds |
}; |
static uintptr_t i8042_physical; |
static uintptr_t i8042_kernel; |
static i8042_t * i8042; |
static void wait_ready(void) { |
while (pio_read_8(&i8042->status) & i8042_INPUT_FULL) |
; |
} |
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
int mouseenabled = 0; |
void *vaddr; |
i8042_physical = sysinfo_value("kbd.address.physical"); |
i8042_kernel = sysinfo_value("kbd.address.kernel"); |
if (pio_enable((void *) i8042_physical, sizeof(i8042_t), &vaddr) != 0) |
return -1; |
i8042 = vaddr; |
async_set_interrupt_received(i8042_irq_handler); |
/* Disable kbd, enable mouse */ |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->data, i8042_KBD_DISABLE); |
wait_ready(); |
/* Flush all current IO */ |
while (pio_read_8(&i8042->status) & i8042_OUTPUT_FULL) |
(void) pio_read_8(&i8042->data); |
/* Enable kbd */ |
i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data; |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &i8042_kbd); |
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE; |
if (mouseenabled) |
newcontrol |= i8042_MOUSE_IE; |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->data, newcontrol); |
wait_ready(); |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int status = IPC_GET_ARG1(*call); |
if ((status & i8042_MOUSE_DATA)) |
return; |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
return; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/port/sgcn.c |
---|
0,0 → 1,176 |
/* |
* 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_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief SGCN (Serengeti Console) keyboard port driver. |
*/ |
#include <as.h> |
#include <ddi.h> |
#include <async.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <thread.h> |
#include <bool.h> |
#define POLL_INTERVAL 10000 |
/** |
* 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)) |
/** |
* Virtual address mapped to SRAM. |
*/ |
static uintptr_t sram_virt_addr; |
/** |
* SGCN buffer offset within SGCN. |
*/ |
static uintptr_t sram_buffer_offset; |
/* polling thread */ |
static void *sgcn_thread_impl(void *arg); |
static volatile bool polling_disabled = false; |
/** |
* Initializes the SGCN driver. |
* Maps the physical memory (SRAM) and creates the polling thread. |
*/ |
int kbd_port_init(void) |
{ |
sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size")); |
if (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) != 0) { |
printf("SGCN: uspace driver could not map physical memory."); |
return -1; |
} |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
thread_id_t tid; |
int rc; |
rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid); |
if (rc != 0) { |
return rc; |
} |
return 0; |
} |
void kbd_port_yield(void) |
{ |
polling_disabled = true; |
} |
void kbd_port_reclaim(void) |
{ |
polling_disabled = false; |
} |
/** |
* Handler of the "key pressed" event. Reads codes of all the pressed keys from |
* the buffer. |
*/ |
static 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); |
kbd_push_scancode(c); |
} |
} |
/** |
* Thread to poll SGCN for keypresses. |
*/ |
static void *sgcn_thread_impl(void *arg) |
{ |
(void) arg; |
while (1) { |
if (polling_disabled == false) |
sgcn_key_pressed(); |
usleep(POLL_INTERVAL); |
} |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/gxemul.c |
---|
0,0 → 1,95 |
/* |
* Copyright (c) 2007 Michal Kebrt |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @{ |
* @ingroup kbd |
*/ |
/** @file |
* @brief GXEmul keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
#include <ddi.h> |
static irq_cmd_t gxemul_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2, |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
static irq_code_t gxemul_kbd = { |
sizeof(gxemul_cmds) / sizeof(irq_cmd_t), |
gxemul_cmds |
}; |
static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
/** Initializes keyboard handler. */ |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(gxemul_irq_handler); |
gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual"); |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), |
0, &gxemul_kbd); |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** Process data sent when a key is pressed. |
* |
* @param keybuffer Buffer of pressed keys. |
* @param call IPC call. |
* |
* @return Always 1. |
*/ |
static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/ns16550.c |
---|
0,0 → 1,129 |
/* |
* 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 kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief NS16550 port driver. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/bus.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <ddi.h> |
/* NS16550 registers */ |
#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. */ |
#define LSR_DATA_READY 0x01 |
static irq_cmd_t ns16550_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = LSR_DATA_READY, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t ns16550_kbd = { |
sizeof(ns16550_cmds) / sizeof(irq_cmd_t), |
ns16550_cmds |
}; |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
static uintptr_t ns16550_physical; |
static uintptr_t ns16550_kernel; |
int ns16550_port_init(void) |
{ |
void *vaddr; |
async_set_interrupt_received(ns16550_irq_handler); |
ns16550_physical = sysinfo_value("kbd.address.physical"); |
ns16550_kernel = sysinfo_value("kbd.address.kernel"); |
ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG); |
ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG); |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), |
sysinfo_value("kbd.inr"), &ns16550_kbd); |
return pio_enable((void *) ns16550_physical, 8, &vaddr); |
} |
void ns16550_port_yield(void) |
{ |
} |
void ns16550_port_reclaim(void) |
{ |
} |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
if (cir_service) |
async_msg_1(cir_phone, BUS_CLEAR_INTERRUPT, |
IPC_GET_METHOD(*call)); |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/port/msim.c |
---|
0,0 → 1,87 |
/* |
* 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 kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Msim keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
#include <ddi.h> |
irq_cmd_t msim_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t msim_kbd = { |
sizeof(msim_cmds) / sizeof(irq_cmd_t), |
msim_cmds |
}; |
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(msim_irq_handler); |
msim_cmds[0].addr = sysinfo_value("kbd.address.virtual"); |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), |
0, &msim_kbd); |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/sun.c |
---|
0,0 → 1,74 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Sun keyboard virtual port driver. |
*/ |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <sysinfo.h> |
/** Sun keyboard virtual port driver. |
* |
* This is a virtual port driver which can use |
* both ns16550_port_init and z8530_port_init |
* according to the information passed from the |
* kernel. This is just a temporal hack. |
* |
*/ |
int kbd_port_init(void) |
{ |
if (sysinfo_value("kbd.type.z8530")) { |
if (z8530_port_init() == 0) |
return 0; |
} |
if (sysinfo_value("kbd.type.ns16550")) { |
if (ns16550_port_init() == 0) |
return 0; |
} |
return -1; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/ski.c |
---|
0,0 → 1,123 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Ski console keyboard port driver. |
*/ |
#include <stdlib.h> |
#include <unistd.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sys/types.h> |
#include <thread.h> |
#include <bool.h> |
#define SKI_GETCHAR 21 |
#define POLL_INTERVAL 10000 |
static void *ski_thread_impl(void *arg); |
static int32_t ski_getchar(void); |
static volatile bool polling_disabled = false; |
/** Initialize Ski port driver. */ |
int kbd_port_init(void) |
{ |
thread_id_t tid; |
int rc; |
rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid); |
if (rc != 0) { |
return rc; |
} |
return 0; |
} |
void kbd_port_yield(void) |
{ |
polling_disabled = true; |
} |
void kbd_port_reclaim(void) |
{ |
polling_disabled = false; |
} |
/** Thread to poll Ski for keypresses. */ |
static void *ski_thread_impl(void *arg) |
{ |
int32_t c; |
(void) arg; |
while (1) { |
while (polling_disabled == false) { |
c = ski_getchar(); |
if (c == 0) |
break; |
kbd_push_scancode(c); |
} |
usleep(POLL_INTERVAL); |
} |
} |
/** Ask Ski if a key was pressed. |
* |
* Use SSC (Simulator System Call) to get character from the debug console. |
* This call is non-blocking. |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
*/ |
static int32_t ski_getchar(void) |
{ |
uint64_t ch; |
asm volatile ( |
"mov r15 = %1\n" |
"break 0x80000;;\n" /* modifies r8 */ |
"mov %0 = r8;;\n" |
: "=r" (ch) |
: "i" (SKI_GETCHAR) |
: "r15", "r8" |
); |
return (int32_t) ch; |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/z8530.c |
---|
0,0 → 1,117 |
/* |
* Copyright (c) 2006 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Z8530 keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/bus.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sun.h> |
#include <sys/types.h> |
#include <ddi.h> |
#define CHAN_A_STATUS 4 |
#define CHAN_A_DATA 6 |
#define RR0_RCA 1 |
static irq_cmd_t z8530_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = RR0_RCA, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t z8530_kbd = { |
sizeof(z8530_cmds) / sizeof(irq_cmd_t), |
z8530_cmds |
}; |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int z8530_port_init(void) |
{ |
async_set_interrupt_received(z8530_irq_handler); |
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") + |
CHAN_A_STATUS; |
z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.kernel") + |
CHAN_A_DATA; |
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), |
sysinfo_value("kbd.inr"), &z8530_kbd); |
return 0; |
} |
void z8530_port_yield(void) |
{ |
} |
void z8530_port_reclaim(void) |
{ |
} |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
if (cir_service) |
async_msg_1(cir_phone, BUS_CLEAR_INTERRUPT, |
IPC_GET_METHOD(*call)); |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/dummy.c |
---|
0,0 → 1,54 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd_port |
* @brief Dummy keyboard port driver. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#include <kbd_port.h> |
#include <kbd.h> |
int kbd_port_init(void) |
{ |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** @} |
*/ |
/branches/arm/uspace/srv/kbd/port/i8042.h |
---|
0,0 → 1,55 |
/* |
* 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 kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief i8042 port driver. |
*/ |
#ifndef KBD_PORT_i8042_H_ |
#define KBD_PORT_i8042_H_ |
#include <libarch/ddi.h> |
#include <libarch/types.h> |
struct i8042 { |
ioport8_t data; |
uint8_t pad[3]; |
ioport8_t status; |
} __attribute__ ((packed)); |
typedef struct i8042 i8042_t; |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/genarch/include/kbd.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/genarch/include/scanc.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/genarch/src/kbd.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/genarch/gsp.c |
---|
0,0 → 1,289 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** |
* @addtogroup kbdgen generic |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Generic scancode parser. |
* |
* The scancode parser is a simple finite state machine. It is described |
* using sequences of input symbols (scancodes) and the corresponding output |
* value (mods, key pair). When the parser recognizes a sequence, |
* it outputs the value and restarts. If a transition is undefined, |
* the parser restarts, too. |
* |
* Apart from precise values, GSP_DEFAULT allows to catch general cases. |
* I.e. if we knew that after 0x1b 0x4f there always follow two more |
* scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END) |
* with null output. This will force the parser to read the entire sequence, |
* not leaving garbage on the input if it does not recognize the specific |
* sequence. |
*/ |
#include <gsp.h> |
#include <adt/hash_table.h> |
#include <stdlib.h> |
#include <stdio.h> |
#define TRANS_TABLE_CHAINS 256 |
/* |
* Hash table operations for the transition function. |
*/ |
static hash_index_t trans_op_hash(unsigned long key[]); |
static int trans_op_compare(unsigned long key[], hash_count_t keys, |
link_t *item); |
static void trans_op_remove_callback(link_t *item); |
static hash_table_operations_t trans_ops = { |
.hash = trans_op_hash, |
.compare = trans_op_compare, |
.remove_callback = trans_op_remove_callback |
}; |
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input); |
static void trans_insert(gsp_t *p, gsp_trans_t *t); |
static gsp_trans_t *trans_new(void); |
/** Initialise scancode parser. */ |
void gsp_init(gsp_t *p) |
{ |
p->states = 1; |
hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops); |
} |
/** Insert a series of definitions into the parser. |
* |
* @param p The parser. |
* @param defs Definition list. Each definition starts with two output values |
* (mods, key) and continues with a sequence of input values |
* terminated with GSP_END. The definition list is terminated |
* with two zeroes (0, 0) for output values. |
*/ |
int gsp_insert_defs(gsp_t *p, const int *defs) |
{ |
unsigned mods, key; |
const int *dp; |
int rc; |
dp = defs; |
while (1) { |
/* Read the output values. */ |
mods = *dp++; |
key = *dp++; |
if (key == 0) break; |
/* Insert one sequence. */ |
rc = gsp_insert_seq(p, dp, mods, key); |
if (rc != 0) |
return rc; |
/* Skip to the next definition. */ |
while (*dp != GSP_END) |
++dp; |
++dp; |
} |
return 0; |
} |
/** Insert one sequence into the parser. |
* |
* @param p The parser. |
* @param seq Sequence of input values terminated with GSP_END. |
* @param mods Corresponsing output value. |
* @param key Corresponsing output value. |
*/ |
int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key) |
{ |
int state; |
gsp_trans_t *t; |
state = 0; |
t = NULL; |
/* Input sequence must be non-empty. */ |
if (*seq == GSP_END) |
return -1; |
while (*(seq + 1) != GSP_END) { |
t = trans_lookup(p, state, *seq); |
if (t == NULL) { |
/* Create new state. */ |
t = trans_new(); |
t->old_state = state; |
t->input = *seq; |
t->new_state = p->states++; |
t->out_mods = 0; |
t->out_key = 0; |
trans_insert(p, t); |
} |
state = t->new_state; |
++seq; |
} |
/* Process the last transition. */ |
t = trans_lookup(p, state, *seq); |
if (t != NULL) { |
exit(1); |
return -1; /* Conflicting definition. */ |
} |
t = trans_new(); |
t->old_state = state; |
t->input = *seq; |
t->new_state = 0; |
t->out_mods = mods; |
t->out_key = key; |
trans_insert(p, t); |
return 0; |
} |
/** Compute one parser step. |
* |
* Computes the next state and output values for a given state and input. |
* This handles everything including restarts and default branches. |
* |
* @param p The parser. |
* @param state Old state. |
* @param input Input symbol (scancode). |
* @param mods Output value (modifier). |
* @param key Output value (key). |
* @return New state. |
*/ |
int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key) |
{ |
gsp_trans_t *t; |
t = trans_lookup(p, state, input); |
if (t == NULL) { |
t = trans_lookup(p, state, GSP_DEFAULT); |
} |
if (t == NULL) { |
printf("gsp_step: not found\n"); |
*mods = NULL; |
*key = NULL; |
return 0; |
} |
*mods = t->out_mods; |
*key = t->out_key; |
return t->new_state; |
} |
/** Transition function lookup. |
* |
* Returns the value of the transition function for the given state |
* and input. Note that the transition must be specified precisely, |
* to obtain the default branch use input = GSP_DEFAULT. |
* |
* @param p Parser. |
* @param state Current state. |
* @param input Input value. |
* @return The transition or @c NULL if not defined. |
*/ |
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input) |
{ |
link_t *item; |
unsigned long key[2]; |
key[0] = state; |
key[1] = input; |
item = hash_table_find(&p->trans, key); |
if (item == NULL) return NULL; |
return hash_table_get_instance(item, gsp_trans_t, link); |
} |
/** Define a new transition. |
* |
* @param p The parser. |
* @param t Transition with all fields defined. |
*/ |
static void trans_insert(gsp_t *p, gsp_trans_t *t) |
{ |
unsigned long key[2]; |
key[0] = t->old_state; |
key[1] = t->input; |
hash_table_insert(&p->trans, key, &t->link); |
} |
/** Allocate transition structure. */ |
static gsp_trans_t *trans_new(void) |
{ |
gsp_trans_t *t; |
t = malloc(sizeof(gsp_trans_t)); |
if (t == NULL) { |
printf("Memory allocation failed.\n"); |
exit(1); |
} |
return t; |
} |
/* |
* Transition function hash table operations. |
*/ |
static hash_index_t trans_op_hash(unsigned long key[]) |
{ |
return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS; |
} |
static int trans_op_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
gsp_trans_t *t; |
t = hash_table_get_instance(item, gsp_trans_t, link); |
return ((key[0] == (unsigned long) t->old_state) |
&& (key[1] == (unsigned long) t->input)); |
} |
static void trans_op_remove_callback(link_t *item) |
{ |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/genarch/stroke.c |
---|
0,0 → 1,85 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Stroke simulator. |
* |
* When simulating a keyboard using a serial TTY we need to convert the |
* recognized strokes (such as Shift-A) to sequences of key presses and |
* releases (such as 'press Shift, press A, release A, release Shift'). |
* |
*/ |
#include <stroke.h> |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
/** Correspondence between modifers and the modifier keycodes. */ |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
/** Simulate keystroke using sequences of key presses and releases. */ |
void stroke_sim(unsigned mod, unsigned key) |
{ |
int i; |
/* Simulate modifier presses. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KEY_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
/* Simulate key press and release. */ |
if (key != 0) { |
kbd_push_ev(KEY_PRESS, key); |
kbd_push_ev(KEY_RELEASE, key); |
} |
/* Simulate modifier releases. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KEY_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/layout/cz.c |
---|
0,0 → 1,408 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @{ |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <bool.h> |
#include <layout.h> |
static void layout_reset(void); |
static wchar_t layout_parse_ev(console_event_t *ev); |
enum m_state { |
ms_start, |
ms_hacek, |
ms_carka |
}; |
static enum m_state mstate; |
layout_op_t cz_op = { |
layout_reset, |
layout_parse_ev |
}; |
static wchar_t map_lcase[] = { |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
[KC_R] = 'r', |
[KC_T] = 't', |
[KC_Y] = 'z', |
[KC_U] = 'u', |
[KC_I] = 'i', |
[KC_O] = 'o', |
[KC_P] = 'p', |
[KC_A] = 'a', |
[KC_S] = 's', |
[KC_D] = 'd', |
[KC_F] = 'f', |
[KC_G] = 'g', |
[KC_H] = 'h', |
[KC_J] = 'j', |
[KC_K] = 'k', |
[KC_L] = 'l', |
[KC_Z] = 'y', |
[KC_X] = 'x', |
[KC_C] = 'c', |
[KC_V] = 'v', |
[KC_B] = 'b', |
[KC_N] = 'n', |
[KC_M] = 'm', |
}; |
static wchar_t map_ucase[] = { |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
[KC_R] = 'R', |
[KC_T] = 'T', |
[KC_Y] = 'Z', |
[KC_U] = 'U', |
[KC_I] = 'I', |
[KC_O] = 'O', |
[KC_P] = 'P', |
[KC_A] = 'A', |
[KC_S] = 'S', |
[KC_D] = 'D', |
[KC_F] = 'F', |
[KC_G] = 'G', |
[KC_H] = 'H', |
[KC_J] = 'J', |
[KC_K] = 'K', |
[KC_L] = 'L', |
[KC_Z] = 'Y', |
[KC_X] = 'X', |
[KC_C] = 'C', |
[KC_V] = 'V', |
[KC_B] = 'B', |
[KC_N] = 'N', |
[KC_M] = 'M', |
}; |
static wchar_t map_not_shifted[] = { |
[KC_BACKTICK] = ';', |
[KC_1] = '+', |
[KC_MINUS] = '=', |
[KC_RBRACKET] = ')', |
[KC_QUOTE] = L'§', |
[KC_COMMA] = ',', |
[KC_PERIOD] = '.', |
[KC_SLASH] = '-', |
}; |
static wchar_t map_shifted[] = { |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '%', |
[KC_LBRACKET] = '/', |
[KC_RBRACKET] = '(', |
[KC_SEMICOLON] = '"', |
[KC_QUOTE] = '!', |
[KC_BACKSLASH] = '\'', |
[KC_COMMA] = '?', |
[KC_PERIOD] = ':', |
[KC_SLASH] = '_', |
}; |
static wchar_t map_ns_nocaps[] = { |
[KC_2] = L'ě', |
[KC_3] = L'š', |
[KC_4] = L'č', |
[KC_5] = L'ř', |
[KC_6] = L'ž', |
[KC_7] = L'ý', |
[KC_8] = L'á', |
[KC_9] = L'í', |
[KC_0] = L'é', |
[KC_LBRACKET] = L'ú', |
[KC_SEMICOLON] = L'ů' |
}; |
static wchar_t map_ns_caps[] = { |
[KC_2] = L'Ě', |
[KC_3] = L'Š', |
[KC_4] = L'Č', |
[KC_5] = L'Ř', |
[KC_6] = L'Ž', |
[KC_7] = L'Ý', |
[KC_8] = L'Á', |
[KC_9] = L'Í', |
[KC_0] = L'É', |
[KC_LBRACKET] = L'Ú', |
[KC_SEMICOLON] = L'Ů' |
}; |
static wchar_t map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static wchar_t map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static wchar_t map_hacek_lcase[] = { |
[KC_E] = L'ě', |
[KC_R] = L'ř', |
[KC_T] = L'ť', |
[KC_Y] = L'ž', |
[KC_U] = L'ů', |
[KC_S] = L'š', |
[KC_D] = L'ď', |
[KC_C] = L'č', |
[KC_N] = L'ň' |
}; |
static wchar_t map_hacek_ucase[] = { |
[KC_E] = L'Ě', |
[KC_R] = L'Ř', |
[KC_T] = L'Ť', |
[KC_Y] = L'Ž', |
[KC_U] = L'Ů', |
[KC_S] = L'Š', |
[KC_D] = L'Ď', |
[KC_C] = L'Č', |
[KC_N] = L'Ň' |
}; |
static wchar_t map_carka_lcase[] = { |
[KC_E] = L'é', |
[KC_U] = L'ú', |
[KC_I] = L'í', |
[KC_O] = L'ó', |
[KC_A] = L'á', |
[KC_Z] = L'ý', |
}; |
static wchar_t map_carka_ucase[] = { |
[KC_E] = L'É', |
[KC_U] = L'Ú', |
[KC_I] = L'Í', |
[KC_O] = L'Ó', |
[KC_A] = L'Á', |
[KC_Z] = L'Ý', |
}; |
static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length) |
{ |
if (key >= map_length) |
return 0; |
return map[key]; |
} |
static wchar_t parse_ms_hacek(console_event_t *ev) |
{ |
wchar_t c; |
mstate = ms_start; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t)); |
return c; |
} |
static wchar_t parse_ms_carka(console_event_t *ev) |
{ |
wchar_t c; |
mstate = ms_start; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t)); |
return c; |
} |
static wchar_t parse_ms_start(console_event_t *ev) |
{ |
wchar_t c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
if (ev->key == KC_EQUALS) { |
if ((ev->mods & KM_SHIFT) != 0) |
mstate = ms_hacek; |
else |
mstate = ms_carka; |
return 0; |
} |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) == 0) { |
if ((ev->mods & KM_CAPS_LOCK) != 0) |
c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
} |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t)); |
else |
c = 0; |
return c; |
} |
static bool key_is_mod(unsigned key) |
{ |
switch (key) { |
case KC_LSHIFT: |
case KC_RSHIFT: |
case KC_LALT: |
case KC_RALT: |
case KC_LCTRL: |
case KC_RCTRL: |
return true; |
default: |
return false; |
} |
} |
static void layout_reset(void) |
{ |
mstate = ms_start; |
} |
static wchar_t layout_parse_ev(console_event_t *ev) |
{ |
if (ev->type != KEY_PRESS) |
return 0; |
if (key_is_mod(ev->key)) |
return 0; |
switch (mstate) { |
case ms_start: |
return parse_ms_start(ev); |
case ms_hacek: |
return parse_ms_hacek(ev); |
case ms_carka: |
return parse_ms_carka(ev); |
} |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/layout/us_qwerty.c |
---|
0,0 → 1,244 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @{ |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <layout.h> |
static void layout_reset(void); |
static wchar_t layout_parse_ev(console_event_t *ev); |
layout_op_t us_qwerty_op = { |
layout_reset, |
layout_parse_ev |
}; |
static wchar_t map_lcase[] = { |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
[KC_R] = 'r', |
[KC_T] = 't', |
[KC_Y] = 'y', |
[KC_U] = 'u', |
[KC_I] = 'i', |
[KC_O] = 'o', |
[KC_P] = 'p', |
[KC_A] = 'a', |
[KC_S] = 's', |
[KC_D] = 'd', |
[KC_F] = 'f', |
[KC_G] = 'g', |
[KC_H] = 'h', |
[KC_J] = 'j', |
[KC_K] = 'k', |
[KC_L] = 'l', |
[KC_Z] = 'z', |
[KC_X] = 'x', |
[KC_C] = 'c', |
[KC_V] = 'v', |
[KC_B] = 'b', |
[KC_N] = 'n', |
[KC_M] = 'm', |
}; |
static wchar_t map_ucase[] = { |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
[KC_R] = 'R', |
[KC_T] = 'T', |
[KC_Y] = 'Y', |
[KC_U] = 'U', |
[KC_I] = 'I', |
[KC_O] = 'O', |
[KC_P] = 'P', |
[KC_A] = 'A', |
[KC_S] = 'S', |
[KC_D] = 'D', |
[KC_F] = 'F', |
[KC_G] = 'G', |
[KC_H] = 'H', |
[KC_J] = 'J', |
[KC_K] = 'K', |
[KC_L] = 'L', |
[KC_Z] = 'Z', |
[KC_X] = 'X', |
[KC_C] = 'C', |
[KC_V] = 'V', |
[KC_B] = 'B', |
[KC_N] = 'N', |
[KC_M] = 'M', |
}; |
static wchar_t map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '-', |
[KC_EQUALS] = '=', |
[KC_LBRACKET] = '[', |
[KC_RBRACKET] = ']', |
[KC_SEMICOLON] = ';', |
[KC_QUOTE] = '\'', |
[KC_BACKSLASH] = '\\', |
[KC_COMMA] = ',', |
[KC_PERIOD] = '.', |
[KC_SLASH] = '/', |
}; |
static wchar_t map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '_', |
[KC_EQUALS] = '+', |
[KC_LBRACKET] = '{', |
[KC_RBRACKET] = '}', |
[KC_SEMICOLON] = ':', |
[KC_QUOTE] = '"', |
[KC_BACKSLASH] = '|', |
[KC_COMMA] = '<', |
[KC_PERIOD] = '>', |
[KC_SLASH] = '?', |
}; |
static wchar_t map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static wchar_t map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length) |
{ |
if (key >= map_length) |
return 0; |
return map[key]; |
} |
static void layout_reset(void) |
{ |
} |
static wchar_t layout_parse_ev(console_event_t *ev) |
{ |
wchar_t c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t)); |
else |
c = 0; |
return c; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/layout/us_dvorak.c |
---|
0,0 → 1,250 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbd |
* @brief US Dvorak Simplified Keyboard layout. |
* @{ |
*/ |
#include <kbd.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <layout.h> |
static void layout_reset(void); |
static wchar_t layout_parse_ev(console_event_t *ev); |
layout_op_t us_dvorak_op = { |
layout_reset, |
layout_parse_ev |
}; |
static wchar_t map_lcase[] = { |
[KC_R] = 'p', |
[KC_T] = 'y', |
[KC_Y] = 'f', |
[KC_U] = 'g', |
[KC_I] = 'c', |
[KC_O] = 'r', |
[KC_P] = 'l', |
[KC_A] = 'a', |
[KC_S] = 'o', |
[KC_D] = 'e', |
[KC_F] = 'u', |
[KC_G] = 'i', |
[KC_H] = 'd', |
[KC_J] = 'h', |
[KC_K] = 't', |
[KC_L] = 'n', |
[KC_SEMICOLON] = 's', |
[KC_X] = 'q', |
[KC_C] = 'j', |
[KC_V] = 'k', |
[KC_B] = 'x', |
[KC_N] = 'b', |
[KC_M] = 'm', |
[KC_COMMA] = 'w', |
[KC_PERIOD] = 'v', |
[KC_SLASH] = 'z', |
}; |
static wchar_t map_ucase[] = { |
[KC_R] = 'P', |
[KC_T] = 'Y', |
[KC_Y] = 'F', |
[KC_U] = 'G', |
[KC_I] = 'C', |
[KC_O] = 'R', |
[KC_P] = 'L', |
[KC_A] = 'A', |
[KC_S] = 'O', |
[KC_D] = 'E', |
[KC_F] = 'U', |
[KC_G] = 'I', |
[KC_H] = 'D', |
[KC_J] = 'H', |
[KC_K] = 'T', |
[KC_L] = 'N', |
[KC_SEMICOLON] = 'S', |
[KC_X] = 'Q', |
[KC_C] = 'J', |
[KC_V] = 'K', |
[KC_B] = 'X', |
[KC_N] = 'B', |
[KC_M] = 'M', |
[KC_COMMA] = 'W', |
[KC_PERIOD] = 'V', |
[KC_SLASH] = 'Z', |
}; |
static wchar_t map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '[', |
[KC_EQUALS] = ']', |
[KC_Q] = '\'', |
[KC_W] = ',', |
[KC_E] = '.', |
[KC_LBRACKET] = '/', |
[KC_RBRACKET] = '=', |
[KC_QUOTE] = '-', |
[KC_BACKSLASH] = '\\', |
[KC_Z] = ';', |
}; |
static wchar_t map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '{', |
[KC_EQUALS] = '}', |
[KC_Q] = '"', |
[KC_W] = '<', |
[KC_E] = '>', |
[KC_LBRACKET] = '?', |
[KC_RBRACKET] = '+', |
[KC_QUOTE] = '_', |
[KC_BACKSLASH] = '|', |
[KC_Z] = ':', |
}; |
static wchar_t map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static wchar_t map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length) |
{ |
if (key >= map_length) |
return 0; |
return map[key]; |
} |
static void layout_reset(void) |
{ |
} |
static wchar_t layout_parse_ev(console_event_t *ev) |
{ |
wchar_t c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t)); |
else |
c = 0; |
return c; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/key_buffer.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/include/keys.h |
---|
File deleted |
/branches/arm/uspace/srv/kbd/include/gsp.h |
---|
0,0 → 1,84 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Generic scancode parser. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_GSP_H_ |
#define KBD_GSP_H_ |
#include <adt/hash_table.h> |
enum { |
GSP_END = -1, /**< Terminates a sequence. */ |
GSP_DEFAULT = -2 /**< Wildcard, catches unhandled cases. */ |
}; |
/** Scancode parser description */ |
typedef struct { |
/** Transition table, (state, input) -> (state, output) */ |
hash_table_t trans; |
/** Number of states */ |
int states; |
} gsp_t; |
/** Scancode parser transition. */ |
typedef struct { |
link_t link; /**< Link to hash table in @c gsp_t */ |
/* Preconditions */ |
int old_state; /**< State before transition */ |
int input; /**< Input symbol (scancode) */ |
/* Effects */ |
int new_state; /**< State after transition */ |
/* Output emitted during transition */ |
unsigned out_mods; /**< Modifier to emit */ |
unsigned out_key; /**< Keycode to emit */ |
} gsp_trans_t; |
extern void gsp_init(gsp_t *); |
extern int gsp_insert_defs(gsp_t *, const int *); |
extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned); |
extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/layout.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_LAYOUT_H_ |
#define KBD_LAYOUT_H_ |
#include <sys/types.h> |
#include <io/console.h> |
typedef struct { |
void (*reset)(void); |
wchar_t (*parse_ev)(console_event_t *); |
} layout_op_t; |
extern layout_op_t us_qwerty_op; |
extern layout_op_t us_dvorak_op; |
extern layout_op_t cz_op; |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/kbd.h |
---|
27,10 → 27,10 |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
*/ |
/** @file |
*/ |
37,15 → 37,28 |
#ifndef KBD_KBD_H_ |
#define KBD_KBD_H_ |
#include <key_buffer.h> |
#include <keybuffer.h> |
#include <ipc/ipc.h> |
extern int kbd_arch_init(void); |
extern int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call); |
extern int mouse_arch_process(int phoneid, ipc_call_t *call); |
#define KBD_EVENT 1024 |
#define KBD_MS_LEFT 1025 |
#define KBD_MS_RIGHT 1026 |
#define KBD_MS_MIDDLE 1027 |
#define KBD_MS_MOVE 1028 |
typedef enum { |
KBD_YIELD = IPC_FIRST_USER_METHOD, |
KBD_RECLAIM |
} kbd_request_t; |
extern int cir_service; |
extern int cir_phone; |
extern void kbd_push_scancode(int); |
extern void kbd_push_ev(int, unsigned int); |
#endif |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/kbd/include/keybuffer.h |
---|
0,0 → 1,65 |
/* |
* 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 kbdgen |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef __KEYBUFFER_H__ |
#define __KEYBUFFER_H__ |
#include <sys/types.h> |
#include <io/console.h> |
#include <bool.h> |
/** Size of buffer for pressed keys */ |
#define KEYBUFFER_SIZE 128 |
typedef struct { |
console_event_t fifo[KEYBUFFER_SIZE]; |
unsigned long head; |
unsigned long tail; |
unsigned long items; |
} keybuffer_t; |
extern void keybuffer_free(keybuffer_t *); |
extern void keybuffer_init(keybuffer_t *); |
extern size_t keybuffer_available(keybuffer_t *); |
extern bool keybuffer_empty(keybuffer_t *); |
extern void keybuffer_push(keybuffer_t *, const console_event_t *); |
extern bool keybuffer_pop(keybuffer_t *, console_event_t *); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/kbd_port.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_PORT_H_ |
#define KBD_PORT_H_ |
extern int kbd_port_init(void); |
extern void kbd_port_yield(void); |
extern void kbd_port_reclaim(void); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/sun.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Sun keyboard virtual port driver. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_SUN_H_ |
#define KBD_SUN_H_ |
extern int ns16550_port_init(void); |
extern int z8530_port_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/kbd_ctl.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_CTL_H_ |
#define KBD_CTL_H_ |
extern void kbd_ctl_parse_scancode(int); |
extern int kbd_ctl_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/include/stroke.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Generic scancode parser. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_STROKE_H_ |
#define KBD_STROKE_H_ |
extern void stroke_sim(unsigned, unsigned); |
#endif |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/generic/key_buffer.c |
---|
File deleted |
/branches/arm/uspace/srv/kbd/generic/kbd.c |
---|
28,57 → 28,139 |
/** |
* @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
*/ |
/** @file |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <errno.h> |
#include <arch/kbd.h> |
#include <adt/fifo.h> |
#include <io/console.h> |
#include <io/keycode.h> |
#include <kbd.h> |
#include <libadt/fifo.h> |
#include <key_buffer.h> |
#include <async.h> |
#include <keys.h> |
#include <keybuffer.h> |
#include <kbd_port.h> |
#include <kbd_ctl.h> |
#include <layout.h> |
#define NAME "kbd" |
int cons_connected = 0; |
int phone2cons = -1; |
keybuffer_t keybuffer; |
keybuffer_t keybuffer; |
static void irq_handler(ipc_callid_t iid, ipc_call_t *call) |
/** Currently active modifiers. */ |
static unsigned mods = KM_NUM_LOCK; |
/** Currently pressed lock keys. We track these to tackle autorepeat. */ |
static unsigned lock_keys; |
int cir_service = 0; |
int cir_phone = -1; |
#define NUM_LAYOUTS 3 |
static layout_op_t *layout[NUM_LAYOUTS] = { |
&us_qwerty_op, |
&us_dvorak_op, |
&cz_op |
}; |
static int active_layout = 0; |
void kbd_push_scancode(int scancode) |
{ |
int chr; |
/* printf("scancode: 0x%x\n", scancode);*/ |
kbd_ctl_parse_scancode(scancode); |
} |
#ifdef MOUSE_ENABLED |
if (mouse_arch_process(phone2cons, call)) |
return; |
#endif |
kbd_arch_process(&keybuffer, call); |
void kbd_push_ev(int type, unsigned int key) |
{ |
console_event_t ev; |
unsigned mod_mask; |
if (cons_connected && phone2cons != -1) { |
/* |
* recode to ASCII - one interrupt can produce more than one |
* code so result is stored in fifo |
*/ |
while (!keybuffer_empty(&keybuffer)) { |
if (!keybuffer_pop(&keybuffer, (int *)&chr)) |
break; |
switch (key) { |
case KC_LCTRL: mod_mask = KM_LCTRL; break; |
case KC_RCTRL: mod_mask = KM_RCTRL; break; |
case KC_LSHIFT: mod_mask = KM_LSHIFT; break; |
case KC_RSHIFT: mod_mask = KM_RSHIFT; break; |
case KC_LALT: mod_mask = KM_LALT; break; |
case KC_RALT: mod_mask = KM_RALT; break; |
default: mod_mask = 0; break; |
} |
async_msg_1(phone2cons, KBD_PUSHCHAR, chr); |
if (mod_mask != 0) { |
if (type == KEY_PRESS) |
mods = mods | mod_mask; |
else |
mods = mods & ~mod_mask; |
} |
switch (key) { |
case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break; |
case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break; |
case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break; |
default: mod_mask = 0; break; |
} |
if (mod_mask != 0) { |
if (type == KEY_PRESS) { |
/* |
* Only change lock state on transition from released |
* to pressed. This prevents autorepeat from messing |
* up the lock state. |
*/ |
mods = mods ^ (mod_mask & ~lock_keys); |
lock_keys = lock_keys | mod_mask; |
} else { |
lock_keys = lock_keys & ~mod_mask; |
} |
} |
/* |
printf("type: %d\n", type); |
printf("mods: 0x%x\n", mods); |
printf("keycode: %u\n", key); |
*/ |
if (type == KEY_PRESS && (mods & KM_LCTRL) && |
key == KC_F1) { |
active_layout = 0; |
layout[active_layout]->reset(); |
return; |
} |
if (type == KEY_PRESS && (mods & KM_LCTRL) && |
key == KC_F2) { |
active_layout = 1; |
layout[active_layout]->reset(); |
return; |
} |
if (type == KEY_PRESS && (mods & KM_LCTRL) && |
key == KC_F3) { |
active_layout = 2; |
layout[active_layout]->reset(); |
return; |
} |
ev.type = type; |
ev.key = key; |
ev.mods = mods; |
ev.c = layout[active_layout]->parse_ev(&ev); |
async_msg_4(phone2cons, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c); |
} |
static void console_connection(ipc_callid_t iid, ipc_call_t *icall) |
111,6 → 193,14 |
phone2cons = IPC_GET_ARG5(call); |
retval = 0; |
break; |
case KBD_YIELD: |
kbd_port_yield(); |
retval = 0; |
break; |
case KBD_RECLAIM: |
kbd_port_reclaim(); |
retval = 0; |
break; |
default: |
retval = EINVAL; |
} |
125,16 → 215,35 |
ipcarg_t phonead; |
/* Initialize arch dependent parts */ |
if (kbd_arch_init()) |
if (sysinfo_value("kbd.cir.fhc") == 1) |
cir_service = SERVICE_FHC; |
else if (sysinfo_value("kbd.cir.obio") == 1) |
cir_service = SERVICE_OBIO; |
if (cir_service) { |
while (cir_phone < 0) { |
cir_phone = ipc_connect_me_to_blocking(PHONE_NS, cir_service, |
0, 0); |
} |
} |
/* Initialize port driver. */ |
if (kbd_port_init() != 0) |
return -1; |
/* Initialize controller driver. */ |
if (kbd_ctl_init() != 0) |
return -1; |
/* Initialize (reset) layout. */ |
layout[active_layout]->reset(); |
/* Initialize key buffer */ |
keybuffer_init(&keybuffer); |
async_set_client_connection(console_connection); |
async_set_interrupt_received(irq_handler); |
/* Register service at nameserver */ |
/* Register service at nameserver. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_KEYBOARD, 0, 0, &phonead) != 0) |
return -1; |
141,7 → 250,7 |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
/* Not reached. */ |
return 0; |
} |
/branches/arm/uspace/srv/kbd/generic/keybuffer.c |
---|
0,0 → 1,132 |
/* |
* 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 kbdgen |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#include <keybuffer.h> |
#include <futex.h> |
atomic_t keybuffer_futex = FUTEX_INITIALIZER; |
/** Clear key buffer. |
*/ |
void keybuffer_free(keybuffer_t *keybuffer) |
{ |
futex_down(&keybuffer_futex); |
keybuffer->head = 0; |
keybuffer->tail = 0; |
keybuffer->items = 0; |
futex_up(&keybuffer_futex); |
} |
/** Key buffer initialization. |
* |
*/ |
void keybuffer_init(keybuffer_t *keybuffer) |
{ |
keybuffer_free(keybuffer); |
} |
/** Get free space in buffer. |
* |
* This function is useful for processing some scancodes that are translated |
* to more than one character. |
* |
* @return empty buffer space |
* |
*/ |
size_t keybuffer_available(keybuffer_t *keybuffer) |
{ |
return KEYBUFFER_SIZE - keybuffer->items; |
} |
/** |
* |
* @return nonzero, if buffer is not empty. |
* |
*/ |
bool keybuffer_empty(keybuffer_t *keybuffer) |
{ |
return (keybuffer->items == 0); |
} |
/** Push key event to key buffer. |
* |
* If the buffer is full, the event is ignored. |
* |
* @param keybuffer The keybuffer. |
* @param ev The event to push. |
* |
*/ |
void keybuffer_push(keybuffer_t *keybuffer, const console_event_t *ev) |
{ |
futex_down(&keybuffer_futex); |
if (keybuffer->items < KEYBUFFER_SIZE) { |
keybuffer->fifo[keybuffer->tail] = *ev; |
keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE; |
keybuffer->items++; |
} |
futex_up(&keybuffer_futex); |
} |
/** Pop event from buffer. |
* |
* @param edst Pointer to where the event should be saved. |
* |
* @return True if an event was popped. |
* |
*/ |
bool keybuffer_pop(keybuffer_t *keybuffer, console_event_t *edst) |
{ |
futex_down(&keybuffer_futex); |
if (keybuffer->items > 0) { |
keybuffer->items--; |
*edst = (keybuffer->fifo[keybuffer->head]); |
keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE; |
futex_up(&keybuffer_futex); |
return true; |
} |
futex_up(&keybuffer_futex); |
return false; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/kbd/Makefile |
---|
31,11 → 31,11 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include ../../../Makefile.config |
CFLAGS += -Iinclude -I../libadt/include |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -Iinclude |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
44,75 → 44,130 |
OUTPUT = kbd |
GENERIC_SOURCES = \ |
generic/kbd.c \ |
generic/key_buffer.c |
genarch/gsp.c \ |
genarch/stroke.c \ |
generic/keybuffer.c |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/kbd.c |
ARCH_SOURCES = |
GENARCH_SOURCES = \ |
layout/cz.c \ |
layout/us_qwerty.c \ |
layout/us_dvorak.c |
ifeq ($(ARCH), ia32) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/mouse.c \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
CFLAGS += -DMOUSE_ENABLED |
ifeq ($(UARCH), amd64) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(ARCH), amd64) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/mouse.c \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
CFLAGS += -DMOUSE_ENABLED |
ifeq ($(UARCH), arm32) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(ARCH), sparc64) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
ifeq ($(UARCH), ia32) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(ARCH), arm32) |
ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/kbd_gxemul.c |
ifeq ($(MACHINE), i460GX) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(MACHINE), qemu_icp) |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/kbd_icp.c \ |
arch/$(ARCH)/src/scanc.c |
ifeq ($(MACHINE), ski) |
GENARCH_SOURCES += \ |
port/ski.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), msim) |
GENARCH_SOURCES += \ |
port/msim.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), lgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(MACHINE), bgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(UARCH), ppc32) |
GENARCH_SOURCES += \ |
port/dummy.c \ |
ctl/stty.c |
endif |
ifeq ($(UARCH), sparc64) |
ifeq ($(MACHINE),serengeti) |
GENARCH_SOURCES += \ |
port/sgcn.c \ |
ctl/stty.c |
else |
GENARCH_SOURCES += \ |
port/sun.c \ |
port/z8530.c \ |
port/ns16550.c \ |
ctl/sun.c |
endif |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES))) |
OBJECTS := $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) |
.PHONY: all clean depend disasm links |
all: links $(OUTPUT) $(OUTPUT).disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
links: |
ln -sfn ../arch/$(ARCH)/include include/arch |
ln -sfn ../genarch/include include/genarch |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend include/arch include/genarch |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/vfs/vfs_ops.c |
---|
28,11 → 28,11 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs_ops.c |
* @brief Operations that VFS offers to its clients. |
* @file vfs_ops.c |
* @brief Operations that VFS offers to its clients. |
*/ |
#include "vfs.h" |
43,9 → 43,8 |
#include <stdlib.h> |
#include <string.h> |
#include <bool.h> |
#include <futex.h> |
#include <rwlock.h> |
#include <libadt/list.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <unistd.h> |
#include <ctype.h> |
#include <fcntl.h> |
59,190 → 58,109 |
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a |
* concurrent VFS operation which modifies the file system namespace. |
*/ |
RWLOCK_INITIALIZE(namespace_rwlock); |
FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock); |
futex_t rootfs_futex = FUTEX_INITIALIZER; |
vfs_pair_t rootfs = { |
.fs_handle = 0, |
.dev_handle = 0 |
}; |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
fs_handle_t fs_handle, char *mp, char *opts) |
{ |
dev_handle_t dev_handle; |
vfs_lookup_res_t mp_res; |
vfs_lookup_res_t mr_res; |
vfs_node_t *mp_node = NULL; |
ipc_callid_t callid; |
ipc_call_t data; |
int rc; |
vfs_node_t *mr_node; |
fs_index_t rindex; |
size_t rsize; |
unsigned rlnkcnt; |
ipcarg_t rc; |
int phone; |
size_t size; |
/* |
* We expect the library to do the device-name to device-handle |
* translation for us, thus the device handle will arrive as ARG1 |
* in the request. |
*/ |
dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
/* |
* For now, don't make use of ARG2 and ARG3, but they can be used to |
* carry mount options in the future. |
*/ |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
*/ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Don't receive more than is necessary for storing a full file system |
* name. |
*/ |
if (size < 1 || size > FS_NAME_MAXLEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Deliver the file system name. */ |
char fs_name[FS_NAME_MAXLEN + 1]; |
(void) ipc_data_write_finalize(callid, fs_name, size); |
fs_name[size] = '\0'; |
aid_t msg; |
ipc_call_t answer; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
/* Now, we want the client to send us the mount point. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Check whether size is reasonable wrt. the mount point. */ |
if (size < 1 || size > MAX_PATH_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Allocate buffer for the mount point data being received. */ |
uint8_t *buf; |
buf = malloc(size + 1); |
if (!buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Deliver the mount point. */ |
(void) ipc_data_write_finalize(callid, buf, size); |
buf[size] = '\0'; |
/* Resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
futex_down(&rootfs_futex); |
fibril_rwlock_write_lock(&namespace_rwlock); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
rwlock_write_lock(&namespace_rwlock); |
if ((size == 1) && (buf[0] == '/')) { |
if (str_cmp(mp, "/") == 0) { |
/* Trying to mount root FS over root FS */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
free(buf); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL); |
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL); |
if (rc != EOK) { |
/* The lookup failed for some reason. */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
free(buf); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
mp_node = vfs_node_get(&mp_res); |
if (!mp_node) { |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
free(buf); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Now we hold a reference to mp_node. |
* It will be dropped upon the corresponding VFS_UNMOUNT. |
* It will be dropped upon the corresponding VFS_IN_UNMOUNT. |
* This prevents the mount point from being deleted. |
*/ |
rwlock_write_unlock(&namespace_rwlock); |
} else { |
/* We still don't have the root file system mounted. */ |
if ((size == 1) && (buf[0] == '/')) { |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
if (str_cmp(mp, "/") == 0) { |
/* |
* For this simple, but important case, |
* we are almost done. |
*/ |
free(buf); |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
msg = async_send_1(phone, VFS_OUT_MOUNTED, |
(ipcarg_t) dev_handle, &answer); |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, |
str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc != EOK) { |
futex_up(&rootfs_futex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
rsize = (size_t) IPC_GET_ARG2(answer); |
rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
mr_res.triplet.index = rindex; |
mr_res.size = rsize; |
mr_res.lnkcnt = rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
rootfs.fs_handle = fs_handle; |
rootfs.dev_handle = dev_handle; |
futex_up(&rootfs_futex); |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} else { |
250,38 → 168,266 |
* We can't resolve this without the root filesystem |
* being mounted first. |
*/ |
futex_up(&rootfs_futex); |
free(buf); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
} |
futex_up(&rootfs_futex); |
free(buf); /* The buffer is not needed anymore. */ |
/* |
* At this point, we have all necessary pieces: file system and device |
* handles, and we know the mount point VFS node. |
*/ |
int mountee_phone = vfs_grab_phone(fs_handle); |
assert(mountee_phone >= 0); |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
rc = async_req_4_0(phone, VFS_MOUNT, |
msg = async_send_4(phone, VFS_OUT_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
(ipcarg_t) dev_handle); |
vfs_release_phone(phone); |
(ipcarg_t) dev_handle, &answer); |
/* send connection */ |
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(mountee_phone); |
vfs_release_phone(phone); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
ipc_answer_0(rid, rc); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
return; |
} |
vfs_release_phone(mountee_phone); |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc == EOK) { |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
rsize = (size_t) IPC_GET_ARG2(answer); |
rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = rindex; |
mr_res.size = rsize; |
mr_res.lnkcnt = rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
} else { |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
} |
ipc_answer_0(rid, rc); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* |
* We expect the library to do the device-name to device-handle |
* translation for us, thus the device handle will arrive as ARG1 |
* in the request. |
*/ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* |
* Mount flags are passed as ARG2. |
*/ |
unsigned int flags = (unsigned int) IPC_GET_ARG2(*request); |
/* |
* For now, don't make use of ARG3, but it can be used to |
* carry mount options in the future. |
*/ |
/* We want the client to send us the mount point. */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Check whether size is reasonable wrt. the mount point. */ |
if ((size < 1) || (size > MAX_PATH_LEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Allocate buffer for the mount point data being received. */ |
char *mp = malloc(size + 1); |
if (!mp) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Deliver the mount point. */ |
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(mp); |
return; |
} |
mp[size] = '\0'; |
/* Now we expect to receive the mount options. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Check the offered options size. */ |
if (size < 0 || size > MAX_MNTOPTS_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Allocate buffer for the mount options. */ |
char *opts = (char *) malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
return; |
} |
/* Deliver the mount options. */ |
retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
*/ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
/* |
* Don't receive more than is necessary for storing a full file system |
* name. |
*/ |
if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
/* |
* Allocate buffer for file system name. |
*/ |
char *fs_name = (char *) malloc(size + 1); |
if (fs_name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(opts); |
return; |
} |
/* Deliver the file system name. */ |
retval = ipc_data_write_finalize(callid, fs_name, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
fs_name[size] = '\0'; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
ipc_call_t data; |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
fibril_mutex_lock(&fs_head_lock); |
fs_handle_t fs_handle; |
recheck: |
fs_handle = fs_name_to_handle(fs_name, false); |
if (!fs_handle) { |
if (flags & IPC_FLAG_BLOCKING) { |
fibril_condvar_wait(&fs_head_cv, &fs_head_lock); |
goto recheck; |
} |
fibril_mutex_unlock(&fs_head_lock); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
free(mp); |
free(fs_name); |
free(opts); |
return; |
} |
fibril_mutex_unlock(&fs_head_lock); |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
free(mp); |
free(fs_name); |
free(opts); |
} |
void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
{ |
if (!vfs_files_init()) { |
288,11 → 434,11 |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* The POSIX interface is open(path, oflag, mode). |
* We can receive oflags and mode along with the VFS_OPEN call; the path |
* will need to arrive in another call. |
* We can receive oflags and mode along with the VFS_IN_OPEN call; |
* the path will need to arrive in another call. |
* |
* We also receive one private, non-POSIX set of flags called lflag |
* used to pass information to vfs_lookup_internal(). |
301,19 → 447,30 |
int oflag = IPC_GET_ARG2(*request); |
int mode = IPC_GET_ARG3(*request); |
size_t len; |
/* |
* Make sure that we are called with exactly one of L_FILE and |
* L_DIRECTORY. Make sure that the user does not pass L_OPEN. |
*/ |
if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || |
((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || |
((lflag & L_OPEN) != 0)) { |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (oflag & O_CREAT) |
lflag |= L_CREATE; |
if (oflag & O_EXCL) |
lflag |= L_EXCLUSIVE; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
320,6 → 477,7 |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
334,40 → 492,40 |
* triplet. |
*/ |
if (lflag & L_CREATE) |
rwlock_write_lock(&namespace_rwlock); |
fibril_rwlock_write_lock(&namespace_rwlock); |
else |
rwlock_read_lock(&namespace_rwlock); |
fibril_rwlock_read_lock(&namespace_rwlock); |
/* The path is now populated and we can call vfs_lookup_internal(). */ |
vfs_lookup_res_t lr; |
rc = vfs_lookup_internal(path, lflag, &lr, NULL); |
if (rc) { |
rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL); |
if (rc != EOK) { |
if (lflag & L_CREATE) |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
else |
rwlock_read_unlock(&namespace_rwlock); |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(path); |
return; |
} |
/* Path is no longer needed. */ |
free(path); |
vfs_node_t *node = vfs_node_get(&lr); |
if (lflag & L_CREATE) |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
else |
rwlock_read_unlock(&namespace_rwlock); |
fibril_rwlock_read_unlock(&namespace_rwlock); |
/* Truncate the file if requested and if necessary. */ |
if (oflag & O_TRUNC) { |
rwlock_write_lock(&node->contents_rwlock); |
fibril_rwlock_write_lock(&node->contents_rwlock); |
if (node->size) { |
rc = vfs_truncate_internal(node->fs_handle, |
node->dev_handle, node->index, 0); |
if (rc) { |
rwlock_write_unlock(&node->contents_rwlock); |
fibril_rwlock_write_unlock(&node->contents_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, rc); |
return; |
374,9 → 532,9 |
} |
node->size = 0; |
} |
rwlock_write_unlock(&node->contents_rwlock); |
fibril_rwlock_write_unlock(&node->contents_rwlock); |
} |
/* |
* Get ourselves a file descriptor and the corresponding vfs_file_t |
* structure. |
389,30 → 547,173 |
} |
vfs_file_t *file = vfs_file_get(fd); |
file->node = node; |
if (oflag & O_APPEND) |
if (oflag & O_APPEND) |
file->append = true; |
/* |
* The following increase in reference count is for the fact that the |
* file is being opened and that a file structure is pointing to it. |
* It is necessary so that the file will not disappear when |
* vfs_node_put() is called. The reference will be dropped by the |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
/* Success! Return the new file descriptor to the client. */ |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
{ |
// FIXME: check for sanity of the supplied fs, dev and index |
if (!vfs_files_init()) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* The interface is open_node(fs, dev, index, oflag). |
*/ |
vfs_lookup_res_t lr; |
lr.triplet.fs_handle = IPC_GET_ARG1(*request); |
lr.triplet.dev_handle = IPC_GET_ARG2(*request); |
lr.triplet.index = IPC_GET_ARG3(*request); |
int oflag = IPC_GET_ARG4(*request); |
fibril_rwlock_read_lock(&namespace_rwlock); |
int rc = vfs_open_node_internal(&lr); |
if (rc != EOK) { |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
vfs_node_t *node = vfs_node_get(&lr); |
fibril_rwlock_read_unlock(&namespace_rwlock); |
/* Truncate the file if requested and if necessary. */ |
if (oflag & O_TRUNC) { |
fibril_rwlock_write_lock(&node->contents_rwlock); |
if (node->size) { |
rc = vfs_truncate_internal(node->fs_handle, |
node->dev_handle, node->index, 0); |
if (rc) { |
fibril_rwlock_write_unlock(&node->contents_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, rc); |
return; |
} |
node->size = 0; |
} |
fibril_rwlock_write_unlock(&node->contents_rwlock); |
} |
/* |
* Get ourselves a file descriptor and the corresponding vfs_file_t |
* structure. |
*/ |
int fd = vfs_fd_alloc(); |
if (fd < 0) { |
vfs_node_put(node); |
ipc_answer_0(rid, fd); |
return; |
} |
vfs_file_t *file = vfs_file_get(fd); |
file->node = node; |
if (oflag & O_APPEND) |
file->append = true; |
/* |
* The following increase in reference count is for the fact that the |
* file is being opened and that a file structure is pointing to it. |
* It is necessary so that the file will not disappear when |
* vfs_node_put() is called. The reference will be dropped by the |
* respective VFS_CLOSE. |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
/* Success! Return the new file descriptor to the client. */ |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
void vfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
int rc = vfs_fd_free(fd); |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* |
* Lock the open file structure so that no other thread can manipulate |
* the same open file at a time. |
*/ |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_OUT_SYMC request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev_handle, |
file->node->index, &answer); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, rc); |
} |
void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* |
* Lock the open file structure so that no other thread can manipulate |
* the same open file at a time. |
*/ |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_OUT_CLOSE request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle, |
file->node->index, &answer); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
fibril_mutex_unlock(&file->lock); |
int retval = IPC_GET_ARG1(answer); |
if (retval != EOK) |
ipc_answer_0(rid, retval); |
retval = vfs_fd_free(fd); |
ipc_answer_0(rid, retval); |
} |
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
{ |
455,16 → 756,25 |
* Lock the open file structure so that no other thread can manipulate |
* the same open file at a time. |
*/ |
futex_down(&file->lock); |
fibril_mutex_lock(&file->lock); |
/* |
* Lock the file's node so that no other client can read/write to it at |
* the same time. |
*/ |
if (read) |
rwlock_read_lock(&file->node->contents_rwlock); |
fibril_rwlock_read_lock(&file->node->contents_rwlock); |
else |
rwlock_write_lock(&file->node->contents_rwlock); |
fibril_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); |
fibril_rwlock_read_lock(&namespace_rwlock); |
} |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
473,7 → 783,7 |
ipc_call_t answer; |
if (!read && file->append) |
file->pos = file->node->size; |
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request), |
msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, |
file->node->dev_handle, file->node->index, file->pos, &answer); |
/* |
483,28 → 793,32 |
* don't have to bother. |
*/ |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
if (file->node->type == VFS_NODE_DIRECTORY) |
fibril_rwlock_read_unlock(&namespace_rwlock); |
/* Unlock the VFS node. */ |
if (read) |
rwlock_read_unlock(&file->node->contents_rwlock); |
fibril_rwlock_read_unlock(&file->node->contents_rwlock); |
else { |
/* Update the cached version of node's size. */ |
if (rc == EOK) |
file->node->size = IPC_GET_ARG2(answer); |
rwlock_write_unlock(&file->node->contents_rwlock); |
fibril_rwlock_write_unlock(&file->node->contents_rwlock); |
} |
/* Update the position pointer and unlock the open file. */ |
if (rc == EOK) |
file->pos += bytes; |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
/* |
* FS server's reply is the final result of the whole operation we |
538,40 → 852,40 |
} |
off_t newpos; |
futex_down(&file->lock); |
fibril_mutex_lock(&file->lock); |
if (whence == SEEK_SET) { |
file->pos = off; |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_1(rid, EOK, off); |
return; |
} |
if (whence == SEEK_CUR) { |
if (file->pos + off < file->pos) { |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, EOVERFLOW); |
return; |
} |
file->pos += off; |
newpos = file->pos; |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_1(rid, EOK, newpos); |
return; |
} |
if (whence == SEEK_END) { |
rwlock_read_lock(&file->node->contents_rwlock); |
fibril_rwlock_read_lock(&file->node->contents_rwlock); |
size_t size = file->node->size; |
rwlock_read_unlock(&file->node->contents_rwlock); |
fibril_rwlock_read_unlock(&file->node->contents_rwlock); |
if (size + off < size) { |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, EOVERFLOW); |
return; |
} |
newpos = size + off; |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_1(rid, EOK, newpos); |
return; |
} |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, EINVAL); |
} |
583,7 → 897,7 |
int fs_phone; |
fs_phone = vfs_grab_phone(fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle, |
rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle, |
(ipcarg_t)index, (ipcarg_t)size); |
vfs_release_phone(fs_phone); |
return (int)rc; |
600,19 → 914,119 |
ipc_answer_0(rid, ENOENT); |
return; |
} |
futex_down(&file->lock); |
fibril_mutex_lock(&file->lock); |
rwlock_write_lock(&file->node->contents_rwlock); |
fibril_rwlock_write_lock(&file->node->contents_rwlock); |
rc = vfs_truncate_internal(file->node->fs_handle, |
file->node->dev_handle, file->node->index, size); |
if (rc == EOK) |
file->node->size = size; |
rwlock_write_unlock(&file->node->contents_rwlock); |
fibril_rwlock_write_unlock(&file->node->contents_rwlock); |
futex_up(&file->lock); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, (ipcarg_t)rc); |
} |
void vfs_fstat(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
size_t size = IPC_GET_ARG2(*request); |
ipcarg_t rc; |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
if (!ipc_data_read_receive(&callid, NULL)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
aid_t msg; |
msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle, |
file->node->index, true, NULL); |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
vfs_release_phone(fs_phone); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, rc); |
} |
void vfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
size_t len; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
free(path); |
return; |
} |
path[len] = '\0'; |
if (!ipc_data_read_receive(&callid, NULL)) { |
free(path); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
vfs_lookup_res_t lr; |
fibril_rwlock_read_lock(&namespace_rwlock); |
rc = vfs_lookup_internal(path, L_NONE, &lr, NULL); |
free(path); |
if (rc != EOK) { |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(callid, rc); |
ipc_answer_0(rid, rc); |
return; |
} |
vfs_node_t *node = vfs_node_get(&lr); |
if (!node) { |
fibril_rwlock_read_unlock(&namespace_rwlock); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fibril_rwlock_read_unlock(&namespace_rwlock); |
int fs_phone = vfs_grab_phone(node->fs_handle); |
aid_t msg; |
msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev_handle, |
node->index, false, NULL); |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
ipcarg_t rv; |
async_wait_for(msg, &rv); |
vfs_release_phone(fs_phone); |
ipc_answer_0(rid, rv); |
vfs_node_put(node); |
} |
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request) |
{ |
int mode = IPC_GET_ARG1(*request); |
639,10 → 1053,10 |
} |
path[len] = '\0'; |
rwlock_write_lock(&namespace_rwlock); |
fibril_rwlock_write_lock(&namespace_rwlock); |
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE; |
rc = vfs_lookup_internal(path, lflag, NULL, NULL); |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
free(path); |
ipc_answer_0(rid, rc); |
} |
673,13 → 1087,13 |
} |
path[len] = '\0'; |
rwlock_write_lock(&namespace_rwlock); |
fibril_rwlock_write_lock(&namespace_rwlock); |
lflag &= L_DIRECTORY; /* sanitize lflag */ |
vfs_lookup_res_t lr; |
rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL); |
free(path); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
687,13 → 1101,13 |
/* |
* The name has already been unlinked by vfs_lookup_internal(). |
* We have to get and put the VFS node to ensure that it is |
* VFS_DESTROY'ed after the last reference to it is dropped. |
* VFS_OUT_DESTROY'ed after the last reference to it is dropped. |
*/ |
vfs_node_t *node = vfs_node_get(&lr); |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
node->lnkcnt--; |
futex_up(&nodes_futex); |
rwlock_write_unlock(&namespace_rwlock); |
fibril_mutex_unlock(&nodes_mutex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, EOK); |
} |
700,37 → 1114,37 |
void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
{ |
size_t len; |
size_t olen, nlen; |
ipc_callid_t callid; |
int rc; |
/* Retrieve the old path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
if (!ipc_data_write_receive(&callid, &olen)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *old = malloc(len + 1); |
char *old = malloc(olen + 1); |
if (!old) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, old, len))) { |
if ((rc = ipc_data_write_finalize(callid, old, olen))) { |
ipc_answer_0(rid, rc); |
free(old); |
return; |
} |
old[len] = '\0'; |
old[olen] = '\0'; |
/* Retrieve the new path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
if (!ipc_data_write_receive(&callid, &nlen)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(old); |
return; |
} |
char *new = malloc(len + 1); |
char *new = malloc(nlen + 1); |
if (!new) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
737,16 → 1151,16 |
free(old); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, new, len))) { |
if ((rc = ipc_data_write_finalize(callid, new, nlen))) { |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
new[len] = '\0'; |
new[nlen] = '\0'; |
char *oldc = canonify(old, &len); |
char *newc = canonify(new, NULL); |
char *oldc = canonify(old, &olen); |
char *newc = canonify(new, &nlen); |
if (!oldc || !newc) { |
ipc_answer_0(rid, EINVAL); |
free(old); |
753,8 → 1167,18 |
free(new); |
return; |
} |
if (!strncmp(newc, oldc, len)) { |
/* oldc is a prefix of newc */ |
oldc[olen] = '\0'; |
newc[nlen] = '\0'; |
if ((!str_lcmp(newc, oldc, str_length(oldc))) && |
((newc[str_length(oldc)] == '/') || |
(str_length(oldc) == 1) || |
(str_length(oldc) == str_length(newc)))) { |
/* |
* oldc is a prefix of newc and either |
* - newc continues with a / where oldc ends, or |
* - oldc was / itself, or |
* - oldc and newc are equal. |
*/ |
ipc_answer_0(rid, EINVAL); |
free(old); |
free(new); |
764,11 → 1188,11 |
vfs_lookup_res_t old_lr; |
vfs_lookup_res_t new_lr; |
vfs_lookup_res_t new_par_lr; |
rwlock_write_lock(&namespace_rwlock); |
fibril_rwlock_write_lock(&namespace_rwlock); |
/* Lookup the node belonging to the old file name. */ |
rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
776,16 → 1200,31 |
} |
vfs_node_t *old_node = vfs_node_get(&old_lr); |
if (!old_node) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
free(old); |
free(new); |
return; |
} |
/* Determine the path to the parent of the node with the new name. */ |
char *parentc = str_dup(newc); |
if (!parentc) { |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
char *lastsl = str_rchr(parentc + 1, '/'); |
if (lastsl) |
*lastsl = '\0'; |
else |
parentc[1] = '\0'; |
/* Lookup parent of the new file name. */ |
rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); |
free(parentc); /* not needed anymore */ |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
794,7 → 1233,7 |
/* Check whether linking to the same file system instance. */ |
if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || |
(old_node->dev_handle != new_par_lr.triplet.dev_handle)) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, EXDEV); /* different file systems */ |
free(old); |
free(new); |
810,18 → 1249,18 |
case EOK: |
new_node = vfs_node_get(&new_lr); |
if (!new_node) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
free(old); |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
new_node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
break; |
default: |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOTEMPTY); |
free(old); |
free(new); |
830,7 → 1269,7 |
/* Create the new link for the new name. */ |
rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
if (new_node) |
vfs_node_put(new_node); |
ipc_answer_0(rid, rc); |
838,13 → 1277,13 |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
old_node->lnkcnt++; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
/* Destroy the link for the old name. */ |
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
vfs_node_put(new_node); |
853,10 → 1292,10 |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
old_node->lnkcnt--; |
futex_up(&nodes_futex); |
rwlock_write_unlock(&namespace_rwlock); |
fibril_mutex_unlock(&nodes_mutex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
vfs_node_put(new_node); |
867,4 → 1306,4 |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/vfs/vfs.c |
---|
28,11 → 28,11 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs.c |
* @brief VFS service for HelenOS. |
* @file vfs.c |
* @brief VFS service for HelenOS. |
*/ |
#include <ipc/ipc.h> |
43,17 → 43,14 |
#include <bool.h> |
#include <string.h> |
#include <as.h> |
#include <libadt/list.h> |
#include <atomic.h> |
#include "vfs.h" |
#define NAME "vfs" |
#define dprintf(...) printf(__VA_ARGS__) |
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
bool keep_on_going = 1; |
bool keep_on_going = true; |
/* |
* The connection was opened via the IPC_CONNECT_ME_TO call. |
60,7 → 57,7 |
* This call needs to be answered. |
*/ |
ipc_answer_0(iid, EOK); |
/* |
* Here we enter the main connection fibril loop. |
* The logic behind this loop and the protocol is that we'd like to keep |
72,71 → 69,76 |
* connection later. |
*/ |
while (keep_on_going) { |
ipc_callid_t callid; |
ipc_call_t call; |
callid = async_get_call(&call); |
ipc_callid_t callid = async_get_call(&call); |
fs_handle_t fs_handle; |
int phone; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
break; |
case VFS_REGISTER: |
case VFS_IN_REGISTER: |
vfs_register(callid, &call); |
keep_on_going = false; |
break; |
case VFS_MOUNT: |
case VFS_IN_MOUNT: |
vfs_mount(callid, &call); |
break; |
case VFS_OPEN: |
case VFS_IN_OPEN: |
vfs_open(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_IN_OPEN_NODE: |
vfs_open_node(callid, &call); |
break; |
case VFS_IN_CLOSE: |
vfs_close(callid, &call); |
break; |
case VFS_READ: |
case VFS_IN_READ: |
vfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_IN_WRITE: |
vfs_write(callid, &call); |
break; |
case VFS_SEEK: |
case VFS_IN_SEEK: |
vfs_seek(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_IN_TRUNCATE: |
vfs_truncate(callid, &call); |
break; |
case VFS_MKDIR: |
case VFS_IN_FSTAT: |
vfs_fstat(callid, &call); |
break; |
case VFS_IN_STAT: |
vfs_stat(callid, &call); |
break; |
case VFS_IN_MKDIR: |
vfs_mkdir(callid, &call); |
break; |
case VFS_UNLINK: |
case VFS_IN_UNLINK: |
vfs_unlink(callid, &call); |
break; |
case VFS_RENAME: |
case VFS_IN_RENAME: |
vfs_rename(callid, &call); |
break; |
case VFS_IN_SYNC: |
vfs_sync(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
} |
} |
/* TODO: cleanup after the client */ |
} |
int main(int argc, char **argv) |
{ |
ipcarg_t phonead; |
printf(NAME ": HelenOS VFS server\n"); |
/* |
* Initialize the list of registered file systems. |
*/ |
list_initialize(&fs_head); |
/* |
* Initialize VFS node hash table. |
*/ |
if (!vfs_nodes_init()) { |
143,16 → 145,16 |
printf(NAME ": Failed to initialize VFS node hash table\n"); |
return ENOMEM; |
} |
/* |
* Allocate and initialize the Path Lookup Buffer. |
*/ |
list_initialize(&plb_head); |
plb = as_get_mappable_page(PLB_SIZE); |
if (!plb) { |
printf(NAME ": Cannot allocate a mappable piece of address space\n"); |
return ENOMEM; |
} |
if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE | |
AS_AREA_CACHEABLE) != plb) { |
printf(NAME ": Cannot create address space area\n"); |
161,7 → 163,7 |
memset(plb, 0, PLB_SIZE); |
/* |
* Set a connectio handling function/fibril. |
* Set a connection handling function/fibril. |
*/ |
async_set_client_connection(vfs_connection); |
168,8 → 170,9 |
/* |
* Register at the naming service. |
*/ |
ipcarg_t phonead; |
ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, 0, &phonead); |
/* |
* Start accepting connections. |
*/ |
180,4 → 183,4 |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/vfs/vfs.h |
---|
28,88 → 28,25 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
#ifndef VFS_VFS_H_ |
#define VFS_VFS_H_ |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#include <futex.h> |
#include <rwlock.h> |
#include <adt/list.h> |
#include <fibril_sync.h> |
#include <sys/types.h> |
#include <devmap.h> |
#include <bool.h> |
#include <ipc/vfs.h> |
// FIXME: according to CONFIG_DEBUG |
// #define dprintf(...) printf(__VA_ARGS__) |
// #define dprintf(...) printf(__VA_ARGS__) |
#define dprintf(...) |
#define VFS_FIRST IPC_FIRST_USER_METHOD |
#define IPC_METHOD_TO_VFS_OP(m) ((m) - VFS_FIRST) |
/* Basic types. */ |
typedef int16_t fs_handle_t; |
typedef int16_t dev_handle_t; |
typedef uint32_t fs_index_t; |
typedef enum { |
VFS_READ = VFS_FIRST, |
VFS_WRITE, |
VFS_TRUNCATE, |
VFS_MOUNT, |
VFS_UNMOUNT, |
VFS_LAST_CMN, /* keep this the last member of this enum */ |
} vfs_request_cmn_t; |
typedef enum { |
VFS_LOOKUP = VFS_LAST_CMN, |
VFS_MOUNTED, |
VFS_DESTROY, |
VFS_LAST_CLNT, /* keep this the last member of this enum */ |
} vfs_request_clnt_t; |
typedef enum { |
VFS_REGISTER = VFS_LAST_CMN, |
VFS_OPEN, |
VFS_CLOSE, |
VFS_SEEK, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_RENAME, |
VFS_LAST_SRV, /* keep this the last member of this enum */ |
} vfs_request_srv_t; |
/** |
* An instance of this structure is associated with a particular FS operation. |
* It tells VFS if the FS supports the operation or maybe if a default one |
* should be used. |
*/ |
typedef enum { |
VFS_OP_NULL = 0, |
VFS_OP_DEFAULT, |
VFS_OP_DEFINED |
} vfs_op_t; |
#define FS_NAME_MAXLEN 20 |
/** |
* A structure like this is passed to VFS by each individual FS upon its |
* registration. It assosiates a human-readable identifier with each |
* registered FS. More importantly, through this structure, the FS announces |
* what operations it supports. |
*/ |
typedef struct { |
/** Unique identifier of the fs. */ |
char name[FS_NAME_MAXLEN + 1]; |
/** Operations. */ |
vfs_op_t ops[VFS_LAST_CLNT - VFS_FIRST]; |
} vfs_info_t; |
/** |
* A structure like this will be allocated for each registered file system. |
*/ |
typedef struct { |
116,7 → 53,7 |
link_t fs_link; |
vfs_info_t vfs_info; |
fs_handle_t fs_handle; |
futex_t phone_futex; /**< Phone serializing futex. */ |
fibril_mutex_t phone_lock; |
ipcarg_t phone; |
} fs_info_t; |
123,8 → 60,8 |
/** |
* VFS_PAIR uniquely represents a file system instance. |
*/ |
#define VFS_PAIR \ |
fs_handle_t fs_handle; \ |
#define VFS_PAIR \ |
fs_handle_t fs_handle; \ |
dev_handle_t dev_handle; |
/** |
134,8 → 71,8 |
* @note fs_handle, dev_handle and index are meant to be returned in one |
* IPC reply. |
*/ |
#define VFS_TRIPLET \ |
VFS_PAIR; \ |
#define VFS_TRIPLET \ |
VFS_PAIR; \ |
fs_index_t index; |
typedef struct { |
146,52 → 83,15 |
VFS_TRIPLET; |
} vfs_triplet_t; |
/* |
* Lookup flags. |
*/ |
/** |
* No lookup flags used. |
*/ |
#define L_NONE 0 |
/** |
* Lookup will succeed only if the object is a regular file. If L_CREATE is |
* specified, an empty file will be created. This flag is mutually exclusive |
* with L_DIRECTORY. |
*/ |
#define L_FILE 1 |
/** |
* Lookup wil succeed only if the object is a directory. If L_CREATE is |
* specified, an empty directory will be created. This flag is mutually |
* exclusive with L_FILE. |
*/ |
#define L_DIRECTORY 2 |
/** |
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the |
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used. |
*/ |
#define L_EXCLUSIVE 4 |
/** |
* L_CREATE is used for creating both regular files and directories. |
*/ |
#define L_CREATE 8 |
/** |
* L_LINK is used for linking to an already existing nodes. |
*/ |
#define L_LINK 16 |
/** |
* L_UNLINK is used to remove leaves from the file system namespace. This flag |
* cannot be passed directly by the client, but will be set by VFS during |
* VFS_UNLINK. |
*/ |
#define L_UNLINK 32 |
/** |
* L_PARENT performs a lookup but returns the triplet of the parent node. |
* This flag may not be combined with any other lookup flag. |
*/ |
#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,12 → 113,15 |
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. */ |
/** |
* Holding this rwlock prevents modifications of the node's contents. |
*/ |
rwlock_t contents_rwlock; |
fibril_rwlock_t contents_rwlock; |
} vfs_node_t; |
/** |
227,7 → 130,7 |
*/ |
typedef struct { |
/** Serializes access to this open file. */ |
futex_t lock; |
fibril_mutex_t lock; |
vfs_node_t *node; |
241,16 → 144,14 |
off_t pos; |
} vfs_file_t; |
extern futex_t nodes_futex; |
extern fibril_mutex_t nodes_mutex; |
extern fibril_condvar_t fs_head_cv; |
extern fibril_mutex_t fs_head_lock; |
extern link_t fs_head; /**< List of registered file systems. */ |
extern vfs_pair_t rootfs; /**< Root file system. */ |
#define MAX_PATH_LEN (64 * 1024) |
#define PLB_SIZE (2 * MAX_PATH_LEN) |
/** Each instance of this type describes one path lookup in progress. */ |
typedef struct { |
link_t plb_link; /**< Active PLB entries list link. */ |
258,12 → 159,14 |
size_t len; /**< Number of characters in this PLB entry. */ |
} plb_entry_t; |
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */ |
extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */ |
extern uint8_t *plb; /**< Path Lookup Buffer */ |
extern link_t plb_head; /**< List of active PLB entries. */ |
#define MAX_MNTOPTS_LEN 256 |
/** Holding this rwlock prevents changes in file system namespace. */ |
extern rwlock_t namespace_rwlock; |
extern fibril_rwlock_t namespace_rwlock; |
extern int vfs_grab_phone(fs_handle_t); |
extern void vfs_release_phone(int); |
270,8 → 173,9 |
extern fs_handle_t fs_name_to_handle(char *, bool); |
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *, |
...); |
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, |
vfs_pair_t *, ...); |
extern int vfs_open_node_internal(vfs_lookup_res_t *); |
extern bool vfs_nodes_init(void); |
extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *); |
293,11 → 197,16 |
extern void vfs_register(ipc_callid_t, ipc_call_t *); |
extern void vfs_mount(ipc_callid_t, ipc_call_t *); |
extern void vfs_open(ipc_callid_t, ipc_call_t *); |
extern void vfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void vfs_sync(ipc_callid_t, ipc_call_t *); |
extern void vfs_close(ipc_callid_t, ipc_call_t *); |
extern void vfs_read(ipc_callid_t, ipc_call_t *); |
extern void vfs_write(ipc_callid_t, ipc_call_t *); |
extern void vfs_seek(ipc_callid_t, ipc_call_t *); |
extern void vfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void vfs_fstat(ipc_callid_t, ipc_call_t *); |
extern void vfs_fstat(ipc_callid_t, ipc_call_t *); |
extern void vfs_stat(ipc_callid_t, ipc_call_t *); |
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *); |
extern void vfs_unlink(ipc_callid_t, ipc_call_t *); |
extern void vfs_rename(ipc_callid_t, ipc_call_t *); |
/branches/arm/uspace/srv/vfs/vfs_node.c |
---|
38,15 → 38,14 |
#include "vfs.h" |
#include <stdlib.h> |
#include <string.h> |
#include <futex.h> |
#include <rwlock.h> |
#include <libadt/hash_table.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <assert.h> |
#include <async.h> |
#include <errno.h> |
/** Futex protecting the VFS node hash table. */ |
futex_t nodes_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the VFS node hash table. */ |
FIBRIL_MUTEX_INITIALIZE(nodes_mutex); |
#define NODES_BUCKETS_LOG 8 |
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG) |
89,9 → 88,9 |
*/ |
void vfs_node_addref(vfs_node_t *node) |
{ |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
_vfs_node_addref(node); |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
} |
/** Decrement reference count of a VFS node. |
105,7 → 104,7 |
bool free_vfs_node = false; |
bool free_fs_node = false; |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
if (node->refcnt-- == 1) { |
/* |
* We are dropping the last reference to this node. |
121,7 → 120,7 |
if (!node->lnkcnt) |
free_fs_node = true; |
} |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
if (free_fs_node) { |
/* |
130,7 → 129,7 |
*/ |
int phone = vfs_grab_phone(node->fs_handle); |
ipcarg_t rc; |
rc = async_req_2_0(phone, VFS_DESTROY, |
rc = async_req_2_0(phone, VFS_OUT_DESTROY, |
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
assert(rc == EOK); |
vfs_release_phone(phone); |
161,12 → 160,12 |
link_t *tmp; |
vfs_node_t *node; |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
tmp = hash_table_find(&nodes, key); |
if (!tmp) { |
node = (vfs_node_t *) malloc(sizeof(vfs_node_t)); |
if (!node) { |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
return NULL; |
} |
memset(node, 0, sizeof(vfs_node_t)); |
175,18 → 174,25 |
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); |
fibril_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); |
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); |
fibril_mutex_unlock(&nodes_mutex); |
return node; |
} |
226,4 → 232,4 |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/vfs/vfs_lookup.c |
---|
28,10 → 28,10 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs_lookup.c |
* @file vfs_lookup.c |
* @brief |
*/ |
42,27 → 42,28 |
#include <string.h> |
#include <stdarg.h> |
#include <bool.h> |
#include <futex.h> |
#include <libadt/list.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <vfs/canonify.h> |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
futex_t plb_futex = FUTEX_INITIALIZER; |
link_t plb_head; /**< PLB entry ring buffer. */ |
FIBRIL_MUTEX_INITIALIZE(plb_mutex); |
LIST_INITIALIZE(plb_head); /**< PLB entry ring buffer. */ |
uint8_t *plb = NULL; |
/** Perform a path lookup. |
* |
* @param path Path to be resolved; it must be a NULL-terminated |
* string. |
* @param lflag Flags to be used during lookup. |
* @param result Empty structure where the lookup result will be stored. |
* Can be NULL. |
* @param altroot If non-empty, will be used instead of rootfs as the root |
* of the whole VFS tree. |
* @param path Path to be resolved; it must be a NULL-terminated |
* string. |
* @param lflag Flags to be used during lookup. |
* @param result Empty structure where the lookup result will be stored. |
* Can be NULL. |
* @param altroot If non-empty, will be used instead of rootfs as the root |
* of the whole VFS tree. |
* |
* @return EOK on success or an error code from errno.h. |
* @return EOK on success or an error code from errno.h. |
* |
*/ |
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result, |
vfs_pair_t *altroot, ...) |
91,7 → 92,7 |
va_end(ap); |
} |
futex_down(&plb_futex); |
fibril_mutex_lock(&plb_mutex); |
plb_entry_t entry; |
link_initialize(&entry.plb_link); |
118,7 → 119,7 |
/* |
* The buffer cannot absorb the path. |
*/ |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
return ELIMIT; |
} |
} else { |
126,7 → 127,7 |
/* |
* The buffer cannot absorb the path. |
*/ |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
return ELIMIT; |
} |
} |
145,7 → 146,7 |
*/ |
list_append(&entry.plb_link, &plb_head); |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
/* |
* Copy the path into PLB. |
158,16 → 159,16 |
ipc_call_t answer; |
int phone = vfs_grab_phone(root->fs_handle); |
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first, |
aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (ipcarg_t) first, |
(ipcarg_t) (first + len - 1) % PLB_SIZE, |
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index, |
&answer); |
vfs_release_phone(phone); |
ipcarg_t rc; |
async_wait_for(req, &rc); |
futex_down(&plb_futex); |
vfs_release_phone(phone); |
fibril_mutex_lock(&plb_mutex); |
list_remove(&entry.plb_link); |
/* |
* Erasing the path from PLB will come handy for debugging purposes. |
174,19 → 175,58 |
*/ |
memset(&plb[first], 0, cnt1); |
memset(plb, 0, cnt2); |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
if ((rc == EOK) && result) { |
if ((rc == EOK) && (result)) { |
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer); |
result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer); |
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; |
} |
/** Perform a node open operation. |
* |
* @return EOK on success or an error code from errno.h. |
* |
*/ |
int vfs_open_node_internal(vfs_lookup_res_t *result) |
{ |
int phone = vfs_grab_phone(result->triplet.fs_handle); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE, |
(ipcarg_t) result->triplet.dev_handle, |
(ipcarg_t) result->triplet.index, &answer); |
ipcarg_t rc; |
async_wait_for(req, &rc); |
vfs_release_phone(phone); |
if (rc == EOK) { |
result->size = (size_t) IPC_GET_ARG1(answer); |
result->lnkcnt = (unsigned) IPC_GET_ARG2(answer); |
if (IPC_GET_ARG3(answer) & L_FILE) |
result->type = VFS_NODE_FILE; |
else if (IPC_GET_ARG3(answer) & L_DIRECTORY) |
result->type = VFS_NODE_DIRECTORY; |
else |
result->type = VFS_NODE_UNKNOWN; |
} |
return rc; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/vfs/vfs_register.c |
---|
28,10 → 28,10 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs_register.c |
* @file vfs_register.c |
* @brief |
*/ |
45,15 → 45,16 |
#include <string.h> |
#include <ctype.h> |
#include <bool.h> |
#include <futex.h> |
#include <libadt/list.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <as.h> |
#include <assert.h> |
#include <atomic.h> |
#include "vfs.h" |
atomic_t fs_head_futex = FUTEX_INITIALIZER; |
link_t fs_head; |
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv); |
FIBRIL_MUTEX_INITIALIZE(fs_head_lock); |
LIST_INITIALIZE(fs_head); |
atomic_t fs_handle_next = { |
.count = 1 |
98,30 → 99,6 |
return false; |
} |
/* |
* Check if the FS implements mandatory VFS operations. |
*/ |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_LOOKUP not defined by the client.\n"); |
return false; |
} |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_READ)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_READ not defined by the client.\n"); |
return false; |
} |
/* |
* Check if each operation is either not defined, defined or default. |
*/ |
for (i = VFS_FIRST; i < VFS_LAST_CLNT; i++) { |
if ((info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_NULL) && |
(info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_DEFAULT) && |
(info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_DEFINED)) { |
dprintf("Operation info not understood.\n"); |
return false; |
} |
} |
return true; |
} |
183,7 → 160,7 |
return; |
} |
link_initialize(&fs_info->fs_link); |
futex_initialize(&fs_info->phone_futex, 1); |
fibril_mutex_initialize(&fs_info->phone_lock); |
rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size); |
if (rc != EOK) { |
204,8 → 181,7 |
return; |
} |
futex_down(&fs_head_futex); |
fibril_inc_sercount(); |
fibril_mutex_lock(&fs_head_lock); |
/* |
* Check for duplicit registrations. |
215,8 → 191,7 |
* We already register a fs like this. |
*/ |
dprintf("FS is already registered.\n"); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
free(fs_info); |
ipc_answer_0(callid, EEXISTS); |
ipc_answer_0(rid, EEXISTS); |
238,8 → 213,7 |
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) { |
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call)); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
free(fs_info); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
257,8 → 231,7 |
if (!ipc_share_in_receive(&callid, &size)) { |
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call)); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
ipc_hangup(fs_info->phone); |
free(fs_info); |
ipc_answer_0(callid, EINVAL); |
272,8 → 245,7 |
if (size != PLB_SIZE) { |
dprintf("Client suggests wrong size of PFB, size = %d\n", size); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
ipc_hangup(fs_info->phone); |
free(fs_info); |
ipc_answer_0(callid, EINVAL); |
297,8 → 269,8 |
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next); |
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
fibril_condvar_broadcast(&fs_head_cv); |
fibril_mutex_unlock(&fs_head_lock); |
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n", |
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle); |
313,76 → 285,49 |
*/ |
int vfs_grab_phone(fs_handle_t handle) |
{ |
int phone; |
/* |
* For now, we don't try to be very clever and very fast. |
* We simply lookup the phone in the fs_head list. We currently don't |
* open any additional phones (even though that itself would be pretty |
* straightforward; housekeeping multiple open phones to a FS task would |
* be more demanding). Instead, we simply take the respective |
* phone_futex and keep it until vfs_release_phone(). |
* For now, we don't try to be very clever and very fast. We simply |
* lookup the phone in the fs_head list and duplicate it. The duplicate |
* phone will be returned to the client and the client will use it for |
* communication. In the future, we should cache the connections so |
* that they do not have to be reestablished over and over again. |
*/ |
futex_down(&fs_head_futex); |
fibril_mutex_lock(&fs_head_lock); |
link_t *cur; |
fs_info_t *fs; |
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) { |
fs = list_get_instance(cur, fs_info_t, fs_link); |
if (fs->fs_handle == handle) { |
futex_up(&fs_head_futex); |
/* |
* For now, take the futex unconditionally. |
* Oh yeah, serialization rocks. |
* It will be up'ed in vfs_release_phone(). |
*/ |
futex_down(&fs->phone_futex); |
/* |
* Avoid deadlock with other fibrils in the same thread |
* by disabling fibril preemption. |
*/ |
fibril_inc_sercount(); |
return fs->phone; |
fibril_mutex_unlock(&fs_head_lock); |
fibril_mutex_lock(&fs->phone_lock); |
phone = ipc_connect_me_to(fs->phone, 0, 0, 0); |
fibril_mutex_unlock(&fs->phone_lock); |
assert(phone > 0); |
return phone; |
} |
} |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
return 0; |
} |
/** Tell VFS that the phone is in use for any request. |
/** Tell VFS that the phone is not needed anymore. |
* |
* @param phone Phone to FS task. |
*/ |
void vfs_release_phone(int phone) |
{ |
bool found = false; |
/* |
* Undo the fibril_inc_sercount() done in vfs_grab_phone(). |
*/ |
fibril_dec_sercount(); |
futex_down(&fs_head_futex); |
link_t *cur; |
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) { |
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link); |
if (fs->phone == phone) { |
found = true; |
futex_up(&fs_head_futex); |
futex_up(&fs->phone_futex); |
return; |
} |
} |
futex_up(&fs_head_futex); |
/* |
* Not good to get here. |
*/ |
assert(found == true); |
/* TODO: implement connection caching */ |
ipc_hangup(phone); |
} |
/** Convert file system name to its handle. |
* |
* @param name File system name. |
* @param lock If true, the function will down and up the |
* fs_head_futex. |
* @param lock If true, the function will lock and unlock the |
* fs_head_lock. |
* |
* @return File system handle or zero if file system not found. |
*/ |
391,18 → 336,17 |
int handle = 0; |
if (lock) |
futex_down(&fs_head_futex); |
fibril_mutex_lock(&fs_head_lock); |
link_t *cur; |
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) { |
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link); |
if (strncmp(fs->vfs_info.name, name, |
sizeof(fs->vfs_info.name)) == 0) { |
if (str_cmp(fs->vfs_info.name, name) == 0) { |
handle = fs->fs_handle; |
break; |
} |
} |
if (lock) |
futex_up(&fs_head_futex); |
fibril_mutex_unlock(&fs_head_lock); |
return handle; |
} |
/branches/arm/uspace/srv/vfs/vfs_file.c |
---|
40,6 → 40,8 |
#include <string.h> |
#include <assert.h> |
#include <bool.h> |
#include <fibril.h> |
#include <fibril_sync.h> |
#include "vfs.h" |
/** |
55,9 → 57,9 |
* first VFS_OPEN operation. |
* |
* This resource being per-connection and, in the first place, per-fibril, we |
* don't need to protect it by a futex. |
* don't need to protect it by a mutex. |
*/ |
__thread vfs_file_t **files = NULL; |
fibril_local vfs_file_t **files = NULL; |
/** Initialize the table of open files. */ |
bool vfs_files_init(void) |
78,19 → 80,23 |
*/ |
int vfs_fd_alloc(void) |
{ |
int i; |
if (!vfs_files_init()) |
return ENOMEM; |
unsigned int i; |
for (i = 0; i < MAX_OPEN_FILES; i++) { |
if (!files[i]) { |
files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t)); |
if (!files[i]) |
return ENOMEM; |
memset(files[i], 0, sizeof(vfs_file_t)); |
futex_initialize(&files[i]->lock, 1); |
fibril_mutex_initialize(&files[i]->lock); |
vfs_file_addref(files[i]); |
return i; |
return (int) i; |
} |
} |
return EMFILE; |
} |
103,10 → 109,15 |
*/ |
int vfs_fd_free(int fd) |
{ |
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
if (!vfs_files_init()) |
return ENOMEM; |
if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
return EBADF; |
vfs_file_delref(files[fd]); |
files[fd] = NULL; |
return EOK; |
} |
150,11 → 161,15 |
*/ |
vfs_file_t *vfs_file_get(int fd) |
{ |
if (fd < MAX_OPEN_FILES) |
if (!vfs_files_init()) |
return NULL; |
if ((fd >= 0) && (fd < MAX_OPEN_FILES)) |
return files[fd]; |
return NULL; |
} |
/** |
* @} |
*/ |
*/ |
/branches/arm/uspace/srv/vfs/Makefile |
---|
32,6 → 32,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
57,18 → 58,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/devmap/devmap.c |
---|
28,9 → 28,9 |
/** |
* @defgroup devmap Device mapper. |
* @brief HelenOS device mapper. |
* @brief HelenOS device mapper. |
* @{ |
*/ |
*/ |
/** @file |
*/ |
41,115 → 41,131 |
#include <stdio.h> |
#include <errno.h> |
#include <bool.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <stdlib.h> |
#include <string.h> |
#include <ipc/devmap.h> |
#define NAME "devmap" |
#define NAME "devmap" |
#define NULL_DEVICES 256 |
/** Representation of device driver. |
* |
* Each driver is responsible for a set of devices. |
* |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Fibril mutex for list of devices owned by this driver */ |
fibril_mutex_t devices_mutex; |
} devmap_driver_t; |
/** Info about registered device |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
dev_handle_t handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
LIST_INITIALIZE(devices_list); |
LIST_INITIALIZE(drivers_list); |
/* order of locking: |
* drivers_list_futex |
* devices_list_futex |
* (devmap_driver_t *)->devices_futex |
* create_handle_futex |
/* Locking order: |
* drivers_list_mutex |
* devices_list_mutex |
* (devmap_driver_t *)->devices_mutex |
* create_handle_mutex |
**/ |
static atomic_t devices_list_futex = FUTEX_INITIALIZER; |
static atomic_t drivers_list_futex = FUTEX_INITIALIZER; |
static atomic_t create_handle_futex = FUTEX_INITIALIZER; |
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex); |
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv); |
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex); |
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex); |
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex); |
static dev_handle_t last_handle = 0; |
static devmap_device_t *null_devices[NULL_DEVICES]; |
static int devmap_create_handle(void) |
static dev_handle_t devmap_create_handle(void) |
{ |
static int last_handle = 0; |
int handle; |
/* TODO: allow reusing old handles after their unregistration |
and implement some version of LRU algorithm */ |
/* FIXME: overflow */ |
futex_down(&create_handle_futex); |
last_handle += 1; |
handle = last_handle; |
futex_up(&create_handle_futex); |
return handle; |
* and implement some version of LRU algorithm, avoid overflow |
*/ |
fibril_mutex_lock(&create_handle_mutex); |
last_handle++; |
fibril_mutex_unlock(&create_handle_mutex); |
return last_handle; |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static int devmap_init() |
{ |
/* TODO: */ |
return EOK; |
} |
/** Find device with given name. |
* |
*/ |
static devmap_device_t *devmap_device_find_name(const char *name) |
{ |
link_t *item; |
link_t *item = devices_list.next; |
devmap_device_t *device = NULL; |
item = devices_list.next; |
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (0 == strcmp(device->name, name)) { |
if (str_cmp(device->name, name) == 0) |
break; |
} |
item = item->next; |
} |
if (item == &devices_list) |
return NULL; |
device = list_get_instance(item, devmap_device_t, devices); |
return device; |
} |
/** Find device with given handle. |
* |
* @todo: use hash table |
* |
*/ |
static devmap_device_t *devmap_device_find_handle(int handle) |
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle) |
{ |
link_t *item; |
fibril_mutex_lock(&devices_list_mutex); |
link_t *item = (&devices_list)->next; |
devmap_device_t *device = NULL; |
futex_down(&devices_list_futex); |
item = (&devices_list)->next; |
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (device->handle == handle) { |
if (device->handle == handle) |
break; |
} |
item = item->next; |
} |
if (item == &devices_list) { |
futex_up(&devices_list_futex); |
fibril_mutex_unlock(&devices_list_mutex); |
return NULL; |
} |
device = list_get_instance(item, devmap_device_t, devices); |
futex_up(&devices_list_futex); |
fibril_mutex_unlock(&devices_list_mutex); |
return device; |
} |
159,14 → 175,12 |
*/ |
static int devmap_device_unregister_core(devmap_device_t *device) |
{ |
list_remove(&(device->devices)); |
list_remove(&(device->driver_devices)); |
free(device->name); |
free(device->name); |
free(device); |
return EOK; |
} |
176,31 → 190,28 |
*/ |
static void devmap_driver_register(devmap_driver_t **odriver) |
{ |
size_t name_size; |
ipc_callid_t callid; |
ipc_call_t call; |
devmap_driver_t *driver; |
ipc_callid_t iid; |
ipc_call_t icall; |
*odriver = NULL; |
iid = async_get_call(&icall); |
ipc_call_t icall; |
ipc_callid_t iid = async_get_call(&icall); |
if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (NULL == |
(driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) { |
} |
devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t)); |
if (driver == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* |
/* |
* Get driver name |
*/ |
ipc_callid_t callid; |
size_t name_size; |
if (!ipc_data_write_receive(&callid, &name_size)) { |
free(driver); |
ipc_answer_0(callid, EREFUSED); |
207,7 → 218,7 |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (name_size > DEVMAP_NAME_MAXLEN) { |
free(driver); |
ipc_answer_0(callid, EINVAL); |
214,43 → 225,45 |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* |
* Allocate buffer for device name. |
*/ |
if (NULL == (driver->name = (char *)malloc(name_size + 1))) { |
driver->name = (char *) malloc(name_size + 1); |
if (driver->name == NULL) { |
free(driver); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
} |
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) { |
if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) { |
free(driver->name); |
free(driver); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
driver->name[name_size] = 0; |
/* Initialize futex for list of devices owned by this driver */ |
futex_initialize(&(driver->devices_futex), 1); |
/* |
/* Initialize mutex for list of devices owned by this driver */ |
fibril_mutex_initialize(&driver->devices_mutex); |
/* |
* Initialize list of asociated devices |
*/ |
list_initialize(&(driver->devices)); |
/* |
* Create connection to the driver |
list_initialize(&driver->devices); |
/* |
* Create connection to the driver |
*/ |
ipc_call_t call; |
callid = async_get_call(&call); |
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) { |
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) { |
ipc_answer_0(callid, ENOTSUP); |
free(driver->name); |
258,73 → 271,71 |
ipc_answer_0(iid, ENOTSUP); |
return; |
} |
driver->phone = IPC_GET_ARG5(call); |
ipc_answer_0(callid, EOK); |
list_initialize(&(driver->drivers)); |
futex_down(&drivers_list_futex); |
fibril_mutex_lock(&drivers_list_mutex); |
/* TODO: |
* check that no driver with name equal to driver->name is registered |
*/ |
/* |
/* |
* Insert new driver into list of registered drivers |
*/ |
list_append(&(driver->drivers), &drivers_list); |
futex_up(&drivers_list_futex); |
fibril_mutex_unlock(&drivers_list_mutex); |
ipc_answer_0(iid, EOK); |
*odriver = driver; |
} |
/** Unregister device driver, unregister all its devices and free driver |
/** |
* Unregister device driver, unregister all its devices and free driver |
* structure. |
* |
*/ |
static int devmap_driver_unregister(devmap_driver_t *driver) |
{ |
devmap_device_t *device; |
if (NULL == driver) |
if (driver == NULL) |
return EEXISTS; |
futex_down(&drivers_list_futex); |
ipc_hangup(driver->phone); |
fibril_mutex_lock(&drivers_list_mutex); |
/* remove it from list of drivers */ |
if (driver->phone != 0) |
ipc_hangup(driver->phone); |
/* Remove it from list of drivers */ |
list_remove(&(driver->drivers)); |
/* unregister all its devices */ |
futex_down(&devices_list_futex); |
futex_down(&(driver->devices_futex)); |
/* Unregister all its devices */ |
fibril_mutex_lock(&devices_list_mutex); |
fibril_mutex_lock(&driver->devices_mutex); |
while (!list_empty(&(driver->devices))) { |
device = list_get_instance(driver->devices.next, |
devmap_device_t *device = list_get_instance(driver->devices.next, |
devmap_device_t, driver_devices); |
devmap_device_unregister_core(device); |
} |
futex_up(&(driver->devices_futex)); |
futex_up(&devices_list_futex); |
futex_up(&drivers_list_futex); |
fibril_mutex_unlock(&driver->devices_mutex); |
fibril_mutex_unlock(&devices_list_mutex); |
fibril_mutex_unlock(&drivers_list_mutex); |
/* free name and driver */ |
if (NULL != driver->name) { |
if (driver->name != NULL) |
free(driver->name); |
} |
free(driver); |
return EOK; |
} |
/** Register instance of device |
* |
*/ |
331,29 → 342,27 |
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall, |
devmap_driver_t *driver) |
{ |
ipc_callid_t callid; |
size_t size; |
devmap_device_t *device; |
if (NULL == driver) { |
if (driver == NULL) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* Create new device entry */ |
if (NULL == |
(device = (devmap_device_t *) malloc(sizeof(devmap_device_t)))) { |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* Get device name */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
free(device); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (size > DEVMAP_NAME_MAXLEN) { |
free(device); |
ipc_answer_0(callid, EINVAL); |
363,8 → 372,8 |
/* +1 for terminating \0 */ |
device->name = (char *) malloc(size + 1); |
if (NULL == device->name) { |
if (device->name == NULL) { |
free(device); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
373,38 → 382,39 |
ipc_data_write_finalize(callid, device->name, size); |
device->name[size] = 0; |
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
futex_down(&devices_list_futex); |
fibril_mutex_lock(&devices_list_mutex); |
/* Check that device with such name is not already registered */ |
if (NULL != devmap_device_find_name(device->name)) { |
printf(NAME ": Device '%s' already registered\n", device->name); |
futex_up(&devices_list_futex); |
fibril_mutex_unlock(&devices_list_mutex); |
free(device->name); |
free(device); |
ipc_answer_0(iid, EEXISTS); |
return; |
} |
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
device->handle = devmap_create_handle(); |
device->driver = driver; |
/* Insert device into list of all devices */ |
list_append(&device->devices, &devices_list); |
/* Insert device into list of devices that belog to one driver */ |
futex_down(&device->driver->devices_futex); |
fibril_mutex_lock(&device->driver->devices_mutex); |
list_append(&device->driver_devices, &device->driver->devices); |
futex_up(&device->driver->devices_futex); |
futex_up(&devices_list_futex); |
fibril_mutex_unlock(&device->driver->devices_mutex); |
fibril_condvar_broadcast(&devices_list_cv); |
fibril_mutex_unlock(&devices_list_mutex); |
ipc_answer_1(iid, EOK, device->handle); |
} |
415,162 → 425,325 |
devmap_driver_t *driver) |
{ |
/* TODO */ |
return EOK; |
} |
/** Connect client to the device. |
* |
* Find device driver owning requested device and forward |
* the message to it. |
* |
*/ |
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) |
{ |
devmap_device_t *dev; |
int handle; |
/* |
* Get handle from request |
*/ |
handle = IPC_GET_ARG2(*call); |
dev = devmap_device_find_handle(handle); |
if (NULL == dev) { |
dev_handle_t handle = IPC_GET_ARG2(*call); |
devmap_device_t *dev = devmap_device_find_handle(handle); |
if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), |
} |
ipc_forward_fast(callid, dev->driver->phone, dev->handle, |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
} |
/** Find handle for device instance identified by name. |
* |
* In answer will be send EOK and device handle in arg1 or a error |
* code from errno.h. |
* code from errno.h. |
* |
*/ |
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall) |
{ |
char *name = NULL; |
size_t name_size; |
const devmap_device_t *dev; |
ipc_callid_t callid; |
ipcarg_t retval; |
/* |
/* |
* Wait for incoming message with device name (but do not |
* read the name itself until the buffer is allocated). |
*/ |
if (!ipc_data_write_receive(&callid, &name_size)) { |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (name_size > DEVMAP_NAME_MAXLEN) { |
if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* |
* Allocate buffer for device name. |
*/ |
if (NULL == (name = (char *)malloc(name_size))) { |
char *name = (char *) malloc(size + 1); |
if (name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
} |
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
if (EOK != (retval = ipc_data_write_finalize(callid, name, |
name_size))) { |
ipcarg_t retval = ipc_data_write_finalize(callid, name, size); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(name); |
return; |
} |
name[size] = '\0'; |
fibril_mutex_lock(&devices_list_mutex); |
const devmap_device_t *dev; |
recheck: |
/* |
* Find device name in linked list of known devices. |
* Find device name in the list of known devices. |
*/ |
dev = devmap_device_find_name(name); |
/* |
* Device was not found. |
*/ |
if (NULL == dev) { |
if (dev == NULL) { |
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) { |
/* Blocking lookup */ |
fibril_condvar_wait(&devices_list_cv, |
&devices_list_mutex); |
goto recheck; |
} |
ipc_answer_0(iid, ENOENT); |
free(name); |
fibril_mutex_unlock(&devices_list_mutex); |
return; |
} |
fibril_mutex_unlock(&devices_list_mutex); |
ipc_answer_1(iid, EOK, dev->handle); |
free(name); |
} |
/** Find name of device identified by id and send it to caller. |
/** Find name of device identified by id and send it to caller. |
* |
*/ |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
{ |
const devmap_device_t *device; |
size_t name_size; |
device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
/* |
* Device not found. |
*/ |
if (NULL == device) { |
if (device == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
} |
ipc_answer_0(iid, EOK); |
size_t name_size = str_size(device->name); |
/* FIXME: |
* We have no channel from DEVMAP to client, therefore |
* sending must be initiated by client. |
* |
* int rc = ipc_data_write_send(phone, device->name, name_size); |
* if (rc != EOK) { |
* async_wait_for(req, NULL); |
* return rc; |
* } |
*/ |
/* TODO: send name in response */ |
} |
name_size = strlen(device->name); |
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
ipc_answer_1(iid, EOK, list_count(&devices_list)); |
fibril_mutex_unlock(&devices_list_mutex); |
} |
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if ((size % sizeof(dev_desc_t)) != 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
size_t count = size / sizeof(dev_desc_t); |
dev_desc_t *desc = (dev_desc_t *) malloc(size); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
size_t pos = 0; |
link_t *item = devices_list.next; |
while ((item != &devices_list) && (pos < count)) { |
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices); |
desc[pos].handle = device->handle; |
str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name); |
pos++; |
item = item->next; |
} |
ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t)); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(desc); |
return; |
} |
free(desc); |
fibril_mutex_unlock(&devices_list_mutex); |
ipc_answer_1(iid, EOK, pos); |
} |
/* FIXME: |
we have no channel from DEVMAP to client -> |
sending must be initiated by client |
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
unsigned int i; |
bool fnd = false; |
for (i = 0; i < NULL_DEVICES; i++) { |
if (null_devices[i] == NULL) { |
fnd = true; |
break; |
} |
} |
if (!fnd) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* Create NULL device entry */ |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
char null[DEVMAP_NAME_MAXLEN]; |
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i); |
device->name = str_dup(null); |
if (device->name == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
free(device); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
fibril_mutex_lock(&devices_list_mutex); |
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
device->driver = NULL; |
/* Insert device into list of all devices |
and into null devices array */ |
list_append(&device->devices, &devices_list); |
null_devices[i] = device; |
fibril_mutex_unlock(&devices_list_mutex); |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_1(iid, EOK, (ipcarg_t) i); |
} |
int rc = ipc_data_write_send(phone, device->name, name_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
ipcarg_t i = IPC_GET_ARG1(*icall); |
if (null_devices[i] == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
*/ |
/* TODO: send name in response */ |
devmap_device_unregister_core(null_devices[i]); |
null_devices[i] = NULL; |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, EOK); |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init(void) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
unsigned int i; |
for (i = 0; i < NULL_DEVICES; i++) |
null_devices[i] = NULL; |
fibril_mutex_unlock(&null_devices_mutex); |
return true; |
} |
/** Handle connection with device driver. |
* |
*/ |
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
bool cont = true; |
devmap_driver_t *driver = NULL; |
ipc_answer_0(iid, EOK); |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
devmap_driver_t *driver = NULL; |
devmap_driver_register(&driver); |
if (NULL == driver) |
return; |
bool cont = true; |
while (cont) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
cont = false; |
continue; /* Exit thread */ |
continue; |
case DEVMAP_DRIVER_UNREGISTER: |
if (NULL == driver) { |
if (NULL == driver) |
ipc_answer_0(callid, ENOENT); |
} else { |
else |
ipc_answer_0(callid, EOK); |
} |
break; |
case DEVMAP_DEVICE_REGISTER: |
/* Register one instance of device */ |
584,23 → 757,21 |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
devmap_get_handle(callid, &call); |
devmap_get_name(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
} |
if (NULL != driver) { |
/* |
if (driver != NULL) { |
/* |
* Unregister the device driver and all its devices. |
*/ |
devmap_driver_unregister(driver); |
driver = NULL; |
} |
} |
/** Handle connection with device client. |
608,37 → 779,44 |
*/ |
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
bool cont = true; |
ipc_answer_0(iid, EOK); /* Accept connection */ |
while (cont) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
cont = false; |
continue; /* Exit thread */ |
continue; |
case DEVMAP_DEVICE_GET_HANDLE: |
devmap_get_handle(callid, &call); |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
/* TODO */ |
devmap_get_name(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_CREATE: |
devmap_null_create(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_DESTROY: |
devmap_null_destroy(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_COUNT: |
devmap_get_count(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_DEVICES: |
devmap_get_devices(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
} |
} |
/** Function for handling connections to devmap |
/** Function for handling connections to devmap |
* |
*/ |
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
656,10 → 834,9 |
devmap_forward(iid, icall); |
break; |
default: |
ipc_answer_0(iid, ENOENT); /* No such interface */ |
/* No such interface */ |
ipc_answer_0(iid, ENOENT); |
} |
/* Cleanup */ |
} |
/** |
669,9 → 846,7 |
{ |
printf(NAME ": HelenOS Device Mapper\n"); |
ipcarg_t phonead; |
if (devmap_init() != 0) { |
if (!devmap_init()) { |
printf(NAME ": Error while initializing service\n"); |
return -1; |
} |
678,13 → 853,15 |
/* Set a handler of incomming connections */ |
async_set_client_connection(devmap_connection); |
/* Register device mapper at naming service */ |
ipcarg_t phonead; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/branches/arm/uspace/srv/devmap/Makefile |
---|
31,12 → 31,11 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
LIBS = $(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
44,7 → 43,7 |
SOURCES = \ |
devmap.c |
CFLAGS += -D$(ARCH) |
CFLAGS += -D$(UARCH) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
55,18 → 54,18 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/arm/uspace/srv/cir/fhc/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = fhc |
SOURCES = \ |
fhc.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/cir/fhc/fhc.c |
---|
0,0 → 1,157 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fhc |
* @{ |
*/ |
/** |
* @file fhc.c |
* @brief FHC bus controller driver. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/bus.h> |
#include <ipc/ns.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include <align.h> |
#include <bool.h> |
#include <errno.h> |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#define NAME "fhc" |
#define FHC_UART_INR 0x39 |
#define FHC_UART_IMAP 0x0 |
#define FHC_UART_ICLR 0x4 |
static void *fhc_uart_phys; |
static volatile uint32_t *fhc_uart_virt; |
static size_t fhc_uart_size; |
/** Handle one connection to fhc. |
* |
* @param iid Hash of the request that opened the connection. |
* @param icall Call data of the request that opened the connection. |
*/ |
static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
ipc_answer_0(iid, EOK); |
while (1) { |
int inr; |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case BUS_CLEAR_INTERRUPT: |
inr = IPC_GET_ARG1(call); |
switch (inr) { |
case FHC_UART_INR: |
fhc_uart_virt[FHC_UART_ICLR] = 0; |
ipc_answer_0(callid, EOK); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
} |
break; |
default: |
ipc_answer_0(callid, EINVAL); |
break; |
} |
} |
} |
/** Initialize the FHC driver. |
* |
* So far, the driver heavily depends on information provided by the kernel via |
* sysinfo. In the future, there should be a standalone FHC driver. |
*/ |
static bool fhc_init(void) |
{ |
ipcarg_t phonead; |
fhc_uart_size = sysinfo_value("fhc.uart.size"); |
fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical"); |
if (!fhc_uart_size) { |
printf(NAME ": no FHC UART registers found\n"); |
return false; |
} |
fhc_uart_virt = as_get_mappable_page(fhc_uart_size); |
int flags = AS_AREA_READ | AS_AREA_WRITE; |
int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt, |
ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) { |
printf(NAME ": Error mapping FHC UART registers\n"); |
return false; |
} |
printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys, |
fhc_uart_size); |
async_set_client_connection(fhc_connection); |
ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead); |
return true; |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS FHC bus controller driver\n"); |
if (!fhc_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
* @} |
*/ |
/branches/arm/uspace/srv/cir/obio/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = obio |
SOURCES = \ |
obio.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/arm/uspace/srv/cir/obio/obio.c |
---|
0,0 → 1,158 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup obio |
* @{ |
*/ |
/** |
* @file obio.c |
* @brief OBIO driver. |
* |
* OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P, |
* there is a piece of the root PCI bus controller address space, which |
* contains interrupt mapping and clear registers for all on-board devices. |
* Although UltraSPARC IIi and U2P are different in general, these registers can |
* be found at the same addresses. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/bus.h> |
#include <ipc/ns.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include <align.h> |
#include <bool.h> |
#include <errno.h> |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#define NAME "obio" |
#define OBIO_SIZE 0x1898 |
#define OBIO_IMR_BASE 0x200 |
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK)) |
#define OBIO_CIR_BASE 0x300 |
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK)) |
#define INO_MASK 0x1f |
static void *base_phys; |
static volatile uint64_t *base_virt; |
/** Handle one connection to obio. |
* |
* @param iid Hash of the request that opened the connection. |
* @param icall Call data of the request that opened the connection. |
*/ |
static void obio_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
ipc_answer_0(iid, EOK); |
while (1) { |
int inr; |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case BUS_CLEAR_INTERRUPT: |
inr = IPC_GET_ARG1(call); |
base_virt[OBIO_CIR(inr & INO_MASK)] = 0; |
ipc_answer_0(callid, EOK); |
break; |
default: |
ipc_answer_0(callid, EINVAL); |
break; |
} |
} |
} |
/** Initialize the OBIO driver. |
* |
* So far, the driver heavily depends on information provided by the kernel via |
* sysinfo. In the future, there should be a standalone OBIO driver. |
*/ |
static bool obio_init(void) |
{ |
ipcarg_t phonead; |
base_phys = (void *) sysinfo_value("obio.base.physical"); |
if (!base_phys) { |
printf(NAME ": no OBIO registers found\n"); |
return false; |
} |
base_virt = as_get_mappable_page(OBIO_SIZE); |
int flags = AS_AREA_READ | AS_AREA_WRITE; |
int retval = physmem_map(base_phys, (void *) base_virt, |
ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) { |
printf(NAME ": Error mapping OBIO registers\n"); |
return false; |
} |
printf(NAME ": OBIO registers with base at %p\n", base_phys); |
async_set_client_connection(obio_connection); |
ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead); |
return true; |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS OBIO driver\n"); |
if (!obio_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
* @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/srv/cir/obio |
---|
Property changes: |
Added: svn:mergeinfo |
/branches/arm/uspace/srv/pci/libpci/names.c |
---|
103,7 → 103,7 |
u32 id34 = id_pair(id3, id4); |
unsigned int h = id_hash(cat, id12, id34); |
struct id_entry *n = a->id_hash[h]; |
int len = strlen((char *) text); |
int len = str_size((char *) text); |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
/branches/arm/uspace/srv/pci/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
52,7 → 53,7 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
$(MAKE) -C libpci clean |
depend: |
60,7 → 61,7 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(MAKE) -C libpci |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
/branches/arm/uspace/dist/readme |
---|
0,0 → 1,10 |
Multilingual text test |
---------------------- |
English: Quick brown fox jumps over the lazy dog |
Czech: Příliš žluťoučký kůň úpěl ďábelské ódy |
Greek: á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε |
Hebrew: משוואת ברנולי היא משוואה בהידרודינמיקה |
Arabic: التوزيع الجغرافي للحمل العنقودي |
Russian: Леннон познакомился с художницей-авангардисткой |
Armenian: ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶ |
/branches/arm/uspace/Makefile |
---|
29,21 → 29,26 |
## Include configuration |
# |
-include Makefile.config |
-include ../Makefile.config |
DIRS = \ |
lib/libc \ |
lib/libfs \ |
lib/libblock \ |
lib/softint \ |
lib/softfloat \ |
srv/bd/ata_bd \ |
srv/bd/file_bd \ |
srv/bd/gxe_bd \ |
srv/bd/rd \ |
srv/ns \ |
srv/loader \ |
srv/fb \ |
srv/kbd \ |
srv/console \ |
srv/rd \ |
srv/fs/fat \ |
srv/fs/tmpfs \ |
srv/fs/devfs \ |
srv/vfs \ |
srv/devmap \ |
app/tetris \ |
51,47 → 56,34 |
app/trace \ |
app/klog \ |
app/init \ |
app/getvc \ |
app/bdsh |
ifeq ($(ARCH), amd64) |
ifeq ($(UARCH),amd64) |
DIRS += srv/pci |
endif |
ifeq ($(ARCH), ia32) |
ifeq ($(UARCH),ia32) |
DIRS += srv/pci |
endif |
ifeq ($(ARCH), mips32) |
CFLAGS += -DCONFIG_MIPS_FPU |
ifeq ($(UARCH),sparc64) |
DIRS += \ |
srv/cir/fhc \ |
srv/cir/obio |
endif |
ifeq ($(ARCH), mips32eb) |
CFLAGS += -DCONFIG_MIPS_FPU |
endif |
BUILDS := $(addsuffix .build,$(DIRS)) |
CLEANS := $(addsuffix .clean,$(DIRS)) |
.PHONY: all config build $(BUILDS) $(CLEANS) clean distclean |
.PHONY: all $(BUILDS) $(CLEANS) clean |
all: |
../tools/config.py uspace.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) |
$(MAKE) -C . build |
all: ../Makefile.config ../config.h ../config.defs $(BUILDS) |
config: |
../tools/config.py uspace.config |
build: $(BUILDS) |
clean: $(CLEANS) |
find $(DIRS) -name '*.o' -follow -exec rm \{\} \; |
find lib/libc -name "_link.ld" -exec rm \{\} \; |
distclean: clean |
-rm Makefile.config |
$(CLEANS): |
-$(MAKE) -C $(basename $@) clean ARCH=$(ARCH) |
-$(MAKE) -C $(basename $@) clean |
$(BUILDS): |
$(MAKE) -C $(basename $@) all ARCH=$(ARCH) COMPILER=$(COMPILER) |
$(MAKE) -C $(basename $@) all |