Subversion Repositories Kolibri OS

Rev

Rev 4246 | Rev 5354 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3263 Serge 1
#include 
2
#include 
3260 Serge 3
#include 
4
#include 
5
#include "i915_drv.h"
6
#include "intel_drv.h"
3480 Serge 7
#include 
3260 Serge 8
 
9
 
10
struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
11
{
12
    struct file *filep;
13
    int count;
14
 
15
    filep = malloc(sizeof(*filep));
16
 
17
    if(unlikely(filep == NULL))
18
        return ERR_PTR(-ENOMEM);
19
 
20
    count = size / PAGE_SIZE;
21
 
22
    filep->pages = kzalloc(sizeof(struct page *) * count, 0);
23
    if(unlikely(filep->pages == NULL))
24
    {
25
        kfree(filep);
26
        return ERR_PTR(-ENOMEM);
27
    };
28
 
29
    filep->count     = count;
30
    filep->allocated = 0;
31
    filep->vma       = NULL;
32
 
3298 Serge 33
//    printf("%s file %p pages %p count %d\n",
34
//              __FUNCTION__,filep, filep->pages, count);
3260 Serge 35
 
36
    return filep;
37
}
38
 
39
struct page *shmem_read_mapping_page_gfp(struct file *filep,
40
                                         pgoff_t index, gfp_t gfp)
41
{
42
    struct page *page;
43
 
44
    if(unlikely(index >= filep->count))
45
        return ERR_PTR(-EINVAL);
46
 
47
    page = filep->pages[index];
48
 
49
    if(unlikely(page == NULL))
50
    {
51
        page = (struct page *)AllocPage();
52
 
53
        if(unlikely(page == NULL))
54
            return ERR_PTR(-ENOMEM);
55
 
56
        filep->pages[index] = page;
4246 Serge 57
//        printf("file %p index %d page %x\n", filep, index, page);
58
//        delay(1);
59
 
3260 Serge 60
    };
61
 
62
    return page;
63
};
3263 Serge 64
 
65
unsigned long vm_mmap(struct file *file, unsigned long addr,
66
         unsigned long len, unsigned long prot,
67
         unsigned long flag, unsigned long offset)
68
{
69
    char *mem, *ptr;
70
    int i;
71
 
72
    if (unlikely(offset + PAGE_ALIGN(len) < offset))
73
        return -EINVAL;
74
    if (unlikely(offset & ~PAGE_MASK))
75
        return -EINVAL;
76
 
77
    mem = UserAlloc(len);
78
    if(unlikely(mem == NULL))
79
        return -ENOMEM;
80
 
81
    for(i = offset, ptr = mem; i < offset+len; i+= 4096, ptr+= 4096)
82
    {
83
        struct page *page;
84
 
85
        page = shmem_read_mapping_page_gfp(file, i/PAGE_SIZE,0);
86
 
87
        if (unlikely(IS_ERR(page)))
88
            goto err;
89
 
90
        MapPage(ptr, (addr_t)page, PG_SHARED|PG_UW);
91
    }
92
 
93
    return (unsigned long)mem;
94
err:
95
    UserFree(mem);
96
    return -ENOMEM;
97
};
98
 
3290 Serge 99
void shmem_file_delete(struct file *filep)
100
{
3298 Serge 101
//    printf("%s file %p pages %p count %d\n",
102
//            __FUNCTION__, filep, filep->pages, filep->count);
3263 Serge 103
 
3290 Serge 104
    if(filep->pages)
105
        kfree(filep->pages);
106
}
3480 Serge 107
 
108
 
109
 
110
static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
111
{
112
        while (bytes) {
113
                if (*start != value)
114
                        return (void *)start;
115
                start++;
116
                bytes--;
117
        }
118
        return NULL;
119
}
120
 
121
/**
122
 * memchr_inv - Find an unmatching character in an area of memory.
123
 * @start: The memory area
124
 * @c: Find a character other than c
125
 * @bytes: The size of the area.
126
 *
127
 * returns the address of the first character other than @c, or %NULL
128
 * if the whole buffer contains just @c.
129
 */
130
void *memchr_inv(const void *start, int c, size_t bytes)
131
{
132
        u8 value = c;
133
        u64 value64;
134
        unsigned int words, prefix;
135
 
136
        if (bytes <= 16)
137
                return check_bytes8(start, value, bytes);
138
 
139
        value64 = value;
140
#if defined(ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
141
        value64 *= 0x0101010101010101;
142
#elif defined(ARCH_HAS_FAST_MULTIPLIER)
143
        value64 *= 0x01010101;
144
        value64 |= value64 << 32;
145
#else
146
        value64 |= value64 << 8;
147
        value64 |= value64 << 16;
148
        value64 |= value64 << 32;
149
#endif
150
 
151
        prefix = (unsigned long)start % 8;
152
        if (prefix) {
153
                u8 *r;
154
 
155
                prefix = 8 - prefix;
156
                r = check_bytes8(start, value, prefix);
157
                if (r)
158
                        return r;
159
                start += prefix;
160
                bytes -= prefix;
161
        }
162
 
163
        words = bytes / 8;
164
 
165
        while (words) {
166
                if (*(u64 *)start != value64)
167
                        return check_bytes8(start, value, 8);
168
                start += 8;
169
                words--;
170
        }
171
 
172
        return check_bytes8(start, value, bytes % 8);
173
}
174
 
175
 
176
 
177
int dma_map_sg(struct device *dev, struct scatterlist *sglist,
178
                           int nelems, int dir)
179
{
180
    struct scatterlist *s;
181
    int i;
182
 
183
    for_each_sg(sglist, s, nelems, i) {
184
        s->dma_address = (dma_addr_t)sg_phys(s);
185
#ifdef CONFIG_NEED_SG_DMA_LENGTH
186
        s->dma_length  = s->length;
187
#endif
188
    }
189
 
190
    return nelems;
191
}
192
 
193
 
194
 
195
#define _U  0x01    /* upper */
196
#define _L  0x02    /* lower */
197
#define _D  0x04    /* digit */
198
#define _C  0x08    /* cntrl */
199
#define _P  0x10    /* punct */
200
#define _S  0x20    /* white space (space/lf/tab) */
201
#define _X  0x40    /* hex digit */
202
#define _SP 0x80    /* hard space (0x20) */
203
 
204
extern const unsigned char _ctype[];
205
 
206
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
207
 
208
#define isalnum(c)  ((__ismask(c)&(_U|_L|_D)) != 0)
209
#define isalpha(c)  ((__ismask(c)&(_U|_L)) != 0)
210
#define iscntrl(c)  ((__ismask(c)&(_C)) != 0)
211
#define isdigit(c)  ((__ismask(c)&(_D)) != 0)
212
#define isgraph(c)  ((__ismask(c)&(_P|_U|_L|_D)) != 0)
213
#define islower(c)  ((__ismask(c)&(_L)) != 0)
214
#define isprint(c)  ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
215
#define ispunct(c)  ((__ismask(c)&(_P)) != 0)
216
/* Note: isspace() must return false for %NUL-terminator */
217
#define isspace(c)  ((__ismask(c)&(_S)) != 0)
218
#define isupper(c)  ((__ismask(c)&(_U)) != 0)
219
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
220
 
221
#define isascii(c) (((unsigned char)(c))<=0x7f)
222
#define toascii(c) (((unsigned char)(c))&0x7f)
223
 
224
static inline unsigned char __tolower(unsigned char c)
225
{
226
    if (isupper(c))
227
        c -= 'A'-'a';
228
    return c;
229
}
230
 
231
static inline unsigned char __toupper(unsigned char c)
232
{
233
    if (islower(c))
234
        c -= 'a'-'A';
235
    return c;
236
}
237
 
238
#define tolower(c) __tolower(c)
239
#define toupper(c) __toupper(c)
240
 
241
/*
242
 * Fast implementation of tolower() for internal usage. Do not use in your
243
 * code.
244
 */
245
static inline char _tolower(const char c)
246
{
247
    return c | 0x20;
248
}
249
 
250
 
251
 
252
//const char hex_asc[] = "0123456789abcdef";
253
 
254
/**
255
 * hex_to_bin - convert a hex digit to its real value
256
 * @ch: ascii character represents hex digit
257
 *
258
 * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
259
 * input.
260
 */
261
int hex_to_bin(char ch)
262
{
263
    if ((ch >= '0') && (ch <= '9'))
264
        return ch - '0';
265
    ch = tolower(ch);
266
    if ((ch >= 'a') && (ch <= 'f'))
267
        return ch - 'a' + 10;
268
    return -1;
269
}
270
EXPORT_SYMBOL(hex_to_bin);
271
 
272
/**
273
 * hex2bin - convert an ascii hexadecimal string to its binary representation
274
 * @dst: binary result
275
 * @src: ascii hexadecimal string
276
 * @count: result length
277
 *
278
 * Return 0 on success, -1 in case of bad input.
279
 */
280
int hex2bin(u8 *dst, const char *src, size_t count)
281
{
282
    while (count--) {
283
        int hi = hex_to_bin(*src++);
284
        int lo = hex_to_bin(*src++);
285
 
286
        if ((hi < 0) || (lo < 0))
287
            return -1;
288
 
289
        *dst++ = (hi << 4) | lo;
290
    }
291
    return 0;
292
}
293
EXPORT_SYMBOL(hex2bin);
294
 
295
/**
296
 * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
297
 * @buf: data blob to dump
298
 * @len: number of bytes in the @buf
299
 * @rowsize: number of bytes to print per line; must be 16 or 32
300
 * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
301
 * @linebuf: where to put the converted data
302
 * @linebuflen: total size of @linebuf, including space for terminating NUL
303
 * @ascii: include ASCII after the hex output
304
 *
305
 * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
306
 * 16 or 32 bytes of input data converted to hex + ASCII output.
307
 *
308
 * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
309
 * to a hex + ASCII dump at the supplied memory location.
310
 * The converted output is always NUL-terminated.
311
 *
312
 * E.g.:
313
 *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
314
 *          linebuf, sizeof(linebuf), true);
315
 *
316
 * example output buffer:
317
 * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
318
 */
319
void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
320
            int groupsize, char *linebuf, size_t linebuflen,
321
            bool ascii)
322
{
323
    const u8 *ptr = buf;
324
    u8 ch;
325
    int j, lx = 0;
326
    int ascii_column;
327
 
328
    if (rowsize != 16 && rowsize != 32)
329
        rowsize = 16;
330
 
331
    if (!len)
332
        goto nil;
333
    if (len > rowsize)      /* limit to one line at a time */
334
        len = rowsize;
335
    if ((len % groupsize) != 0) /* no mixed size output */
336
        groupsize = 1;
337
 
338
    switch (groupsize) {
339
    case 8: {
340
        const u64 *ptr8 = buf;
341
        int ngroups = len / groupsize;
342
 
343
        for (j = 0; j < ngroups; j++)
344
            lx += scnprintf(linebuf + lx, linebuflen - lx,
345
                    "%s%16.16llx", j ? " " : "",
346
                    (unsigned long long)*(ptr8 + j));
347
        ascii_column = 17 * ngroups + 2;
348
        break;
349
    }
350
 
351
    case 4: {
352
        const u32 *ptr4 = buf;
353
        int ngroups = len / groupsize;
354
 
355
        for (j = 0; j < ngroups; j++)
356
            lx += scnprintf(linebuf + lx, linebuflen - lx,
357
                    "%s%8.8x", j ? " " : "", *(ptr4 + j));
358
        ascii_column = 9 * ngroups + 2;
359
        break;
360
    }
361
 
362
    case 2: {
363
        const u16 *ptr2 = buf;
364
        int ngroups = len / groupsize;
365
 
366
        for (j = 0; j < ngroups; j++)
367
            lx += scnprintf(linebuf + lx, linebuflen - lx,
368
                    "%s%4.4x", j ? " " : "", *(ptr2 + j));
369
        ascii_column = 5 * ngroups + 2;
370
        break;
371
    }
372
 
373
    default:
374
        for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
375
            ch = ptr[j];
376
            linebuf[lx++] = hex_asc_hi(ch);
377
            linebuf[lx++] = hex_asc_lo(ch);
378
            linebuf[lx++] = ' ';
379
        }
380
        if (j)
381
            lx--;
382
 
383
        ascii_column = 3 * rowsize + 2;
384
        break;
385
    }
386
    if (!ascii)
387
        goto nil;
388
 
389
    while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
390
        linebuf[lx++] = ' ';
391
    for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) {
392
        ch = ptr[j];
393
        linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
394
    }
395
nil:
396
    linebuf[lx++] = '\0';
397
}
398
 
399
/**
400
 * print_hex_dump - print a text hex dump to syslog for a binary blob of data
401
 * @level: kernel log level (e.g. KERN_DEBUG)
402
 * @prefix_str: string to prefix each line with;
403
 *  caller supplies trailing spaces for alignment if desired
404
 * @prefix_type: controls whether prefix of an offset, address, or none
405
 *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
406
 * @rowsize: number of bytes to print per line; must be 16 or 32
407
 * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
408
 * @buf: data blob to dump
409
 * @len: number of bytes in the @buf
410
 * @ascii: include ASCII after the hex output
411
 *
412
 * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
413
 * to the kernel log at the specified kernel log level, with an optional
414
 * leading prefix.
415
 *
416
 * print_hex_dump() works on one "line" of output at a time, i.e.,
417
 * 16 or 32 bytes of input data converted to hex + ASCII output.
418
 * print_hex_dump() iterates over the entire input @buf, breaking it into
419
 * "line size" chunks to format and print.
420
 *
421
 * E.g.:
422
 *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
423
 *          16, 1, frame->data, frame->len, true);
424
 *
425
 * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
426
 * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
427
 * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
428
 * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
429
 */
430
void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
431
            int rowsize, int groupsize,
432
            const void *buf, size_t len, bool ascii)
433
{
434
    const u8 *ptr = buf;
435
    int i, linelen, remaining = len;
436
    unsigned char linebuf[32 * 3 + 2 + 32 + 1];
437
 
438
    if (rowsize != 16 && rowsize != 32)
439
        rowsize = 16;
440
 
441
    for (i = 0; i < len; i += rowsize) {
442
        linelen = min(remaining, rowsize);
443
        remaining -= rowsize;
444
 
445
        hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
446
                   linebuf, sizeof(linebuf), ascii);
447
 
448
        switch (prefix_type) {
449
        case DUMP_PREFIX_ADDRESS:
450
            printk("%s%s%p: %s\n",
451
                   level, prefix_str, ptr + i, linebuf);
452
            break;
453
        case DUMP_PREFIX_OFFSET:
454
            printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
455
            break;
456
        default:
457
            printk("%s%s%s\n", level, prefix_str, linebuf);
458
            break;
459
        }
460
    }
461
}
462
 
463
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
464
                          const void *buf, size_t len)
465
{
466
    print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
467
                       buf, len, true);
468
}
469
 
4104 Serge 470
void *kmemdup(const void *src, size_t len, gfp_t gfp)
471
{
472
    void *p;
3480 Serge 473
 
4104 Serge 474
    p = kmalloc(len, gfp);
475
    if (p)
476
        memcpy(p, src, len);
477
    return p;
478
}
479
 
480
 
5060 serge 481
 
482
void *kmap(struct page *page)
483
{
484
    void *vaddr;
485
 
486
    vaddr = (void*)MapIoMem(page_to_phys(page), 4096, PG_SW);
487
 
488
    return vaddr;
489
}
490
 
491
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
492
{
493
        const unsigned long *p = addr;
494
        unsigned long result = 0;
495
        unsigned long tmp;
496
 
497
        while (size & ~(BITS_PER_LONG-1)) {
498
                if (~(tmp = *(p++)))
499
                        goto found;
500
                result += BITS_PER_LONG;
501
                size -= BITS_PER_LONG;
502
        }
503
        if (!size)
504
                return result;
505
 
506
        tmp = (*p) | (~0UL << size);
507
        if (tmp == ~0UL)        /* Are any bits zero? */
508
                return result + size;   /* Nope. */
509
found:
510
        return result + ffz(tmp);
511
}
512