OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [xscale/] [picasso/] [current/] [src/] [vga_support.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//        vga_support.c
4
//
5
//        NMI picasso - VGA support
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     gthomas
43
// Contributors:  gthomas
44
// Date:          2001-11-03
45
// Description:   Simple VGA support
46
//####DESCRIPTIONEND####
47
 
48
#include <pkgconf/hal.h>
49
 
50
#include <cyg/infra/diag.h>
51
#include <cyg/hal/hal_io.h>       // IO macros
52
#include <cyg/hal/hal_if.h>       // Virtual vector support
53
#include <cyg/hal/hal_arch.h>     // Register state info
54
#include <cyg/hal/hal_intr.h>     // HAL interrupt macros
55
 
56
#include <cyg/hal/vga_support.h>
57
#include <cyg/hal/hal_cache.h>
58
 
59
#include <cyg/hal/plx.h>          // Localbus I/O
60
 
61
#include <string.h>
62
 
63
#ifdef CYGPKG_ISOINFRA
64
# include <pkgconf/isoinfra.h>
65
# ifdef CYGINT_ISO_STDIO_FORMATTED_IO
66
#  include <stdio.h>  // sscanf
67
# endif
68
#endif
69
 
70
#ifndef FALSE
71
#define FALSE 0
72
#define TRUE  1
73
#endif
74
 
75
// Logical layout
76
#define VGA_WIDTH  640
77
#define VGA_HEIGHT 480
78
#define VGA_DEPTH    8
79
 
80
static int bg = 0;
81
static int fg = 1;
82
 
83
static struct vga_info vga;
84
 
85
struct VGA_ctlr {
86
    unsigned short rev;
87
    unsigned char  enable;
88
    unsigned char  _fill1[13];
89
    struct ADV471 {
90
        unsigned short write_addr;
91
        unsigned short data;
92
        unsigned short pixel_read_mask;
93
        unsigned short read_addr;
94
        unsigned short overlay_data;
95
        unsigned short _fill2[2];
96
        unsigned short overlay_read_addr;
97
    } clut;
98
    unsigned char _fill3[0x100000-0x20];
99
    unsigned char fb[1];
100
};
101
 
102
// Compute the location for a pixel within the framebuffer
103
static cyg_uint8 *
104
vga_fb(int row, int col)
105
{
106
    cyg_uint8 *res = (cyg_uint8 *)((char *)vga.fb+(row*vga.rlen)+(col*vga.stride));
107
    return res;
108
}
109
 
110
void
111
vga_on(bool enable)
112
{
113
    static bool on = false;
114
    volatile struct VGA_ctlr *ctlr = vga.ctlr;
115
 
116
    if (enable) {
117
        if (!on) {
118
            ctlr->enable = 1;
119
        }
120
        on = true;
121
    } else {
122
        ctlr->enable = 0;
123
        on = false;
124
    }
125
}
126
 
127
// Initialize VGA hardware
128
 
129
static void
130
vga_set_cmap(volatile struct VGA_ctlr *ctlr, int index,
131
             int red, int green, int blue)
132
{
133
    if (index > 255) {
134
        // Invalid index
135
        return;
136
    }
137
    ctlr->clut.write_addr = index;  // Select
138
    ctlr->clut.data = red>>2;
139
    ctlr->clut.data = green>>2;
140
    ctlr->clut.data = blue>>2;
141
}
142
 
143
void
144
vga_init(cyg_uint32 *addr)
145
{
146
    volatile struct VGA_ctlr *ctlr;
147
 
148
    ctlr = (volatile struct VGA_ctlr *)addr;
149
    vga.ctlr = (void*)ctlr;
150
    vga.fb = ctlr->fb;
151
    vga.bpp = VGA_DEPTH;
152
    vga.height = VGA_HEIGHT;
153
    vga.width = VGA_WIDTH;
154
    vga.rlen = VGA_WIDTH;
155
    vga.stride = 1;
156
    vga.access_size = 1;
157
    vga_set_cmap(ctlr, 0, 0x00, 0x00, 0x00);  // 0 -> black
158
    vga_set_cmap(ctlr, 1, 0xFF, 0xFF, 0xFF);  // 1 -> white
159
//    diag_printf("VGA init at %p/%p\n", vga.ctlr, vga.fb);
160
    ctlr->enable = 1;
161
}
162
 
163
// Get information about the frame buffer
164
int
165
vga_getinfo(struct vga_info *info)
166
{
167
    if (vga.bpp == 0) {
168
        return 0;  // VGA not initialized
169
    }
170
    *info = vga;
171
    return 1; // Information valid
172
}
173
 
174
// Clear screen
175
void
176
vga_clear(void)
177
{
178
#if 0
179
    cyg_uint32 *fb_row0, *fb_rown;
180
    cyg_uint32 _bg = (bg<<16)|bg;
181
 
182
    fb_row0 = vga_fb(0, 0);
183
    fb_rown = vga_fb(vga_height, 0);
184
    while (fb_row0 != fb_rown) {
185
        *fb_row0++ = _bg;
186
    }
187
#endif
188
}
189
 
190
#ifdef CYGSEM_UE250_VGA_COMM
191
 
192
//
193
// Additional support for VGA/Keyboard as 'console' device
194
//
195
 
196
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
197
#include "banner.xpm"
198
#endif
199
#include "font.h"
200
 
201
// Virtual screen info
202
static int curX = 0;  // Last used position
203
static int curY = 0;
204
//static int width = VGA_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);
205
//static int height = VGA_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);
206
 
207
#define SCREEN_PAN            20
208
#define SCREEN_WIDTH          80
209
#define SCREEN_HEIGHT         (VGA_HEIGHT/FONT_HEIGHT)
210
#define VISIBLE_SCREEN_WIDTH  (VGA_WIDTH/FONT_WIDTH)
211
#define VISIBLE_SCREEN_HEIGHT (VGA_HEIGHT/FONT_HEIGHT)
212
static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];
213
static int screen_height = SCREEN_HEIGHT;
214
static int screen_width = SCREEN_WIDTH;
215
static int screen_pan = 0;
216
 
217
// Usable area on screen [logical pixel rows]
218
static int screen_start = 0;
219
static int screen_end = VGA_HEIGHT/FONT_HEIGHT;
220
 
221
static bool cursor_enable = true;
222
 
223
// Functions
224
static void vga_drawc(cyg_uint8 c, int x, int y);
225
 
226
static __inline__ void
227
set_pixel(int row, int col, unsigned char val)
228
{
229
    unsigned char *pix = (unsigned char *)vga_fb(row, col);
230
    *pix = val;
231
}
232
 
233
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
234
static int
235
_hexdigit(char c)
236
{
237
    if ((c >= '0') && (c <= '9')) {
238
        return c - '0';
239
    } else {
240
        if ((c >= 'A') && (c <= 'F')) {
241
            return (c - 'A') + 0x0A;
242
        } else {
243
            if ((c >= 'a') && (c <= 'f')) {
244
                return (c - 'a') + 0x0a;
245
            }
246
        }
247
    }
248
 
249
    return 0;
250
}
251
 
252
static int
253
_hex(char *cp)
254
{
255
    return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));
256
}
257
 
258
static void
259
parse_color(char *cp, int *red, int *green, int *blue)
260
{
261
    *red = *green = *blue = 0xFF;
262
    while (*cp && (*cp != 'c')) cp++;
263
    if (cp) {
264
        cp += 2;
265
        if (*cp == '#') {
266
            *red = _hex(cp+1);
267
            *green = _hex(cp+3);
268
            *blue = _hex(cp+5);
269
        }
270
    }
271
}
272
 
273
#ifndef CYGINT_ISO_STDIO_FORMATTED_IO
274
static int
275
get_int(unsigned char **_cp)
276
{
277
    char *cp = *_cp;
278
    char c;
279
    int val = 0;
280
 
281
    while ((c = *cp++) && (c != ' ')) {
282
        if ((c >= '0') && (c <= '9')) {
283
            val = val * 10 + (c - '0');
284
        } else {
285
            return -1;
286
        }
287
    }
288
    *_cp = cp;
289
    return val;
290
}
291
#endif
292
 
293
static int
294
show_xpm(char *xpm[], int screen_pos)
295
{
296
    int i, row, col, offset;
297
    unsigned char *cp;
298
    int nrows, ncols, nclrs, cwid;
299
    short color_index;
300
    int red, green, blue;
301
//#define HORRIBLY_SLOW_COLOR_MAPPING
302
#ifdef HORRIBLY_SLOW_COLOR_MAPPING
303
    bool color_match;
304
    short cmap[256][2];
305
    int j;
306
#else
307
    // Caution - this is very GIMP specific
308
    short cmap[256][3];  // Enough room for 256 colors
309
    short cmap_col, cmap_row;
310
    unsigned char std_cmap[] = " .+";
311
#endif
312
 
313
    cp = xpm[0];
314
#ifdef CYGINT_ISO_STDIO_FORMATTED_IO
315
    if (sscanf(cp, "%d %d %d %d", &ncols, &nrows, &nclrs, &cwid) != 4) {
316
#else
317
    if (((ncols = get_int(&cp)) < 0) ||
318
        ((nrows = get_int(&cp)) < 0) ||
319
        ((nclrs = get_int(&cp)) < 0) ||
320
        ((cwid = get_int(&cp)) < 0)) {
321
 
322
#endif
323
        diag_printf("Can't parse XPM data, sorry\n");
324
        return 0;
325
    }
326
//    diag_printf("%d rows, %d cols, %d colors %d chars/pixel\n", nrows, ncols, nclrs, cwid);
327
    if (cwid > 2) {
328
        diag_printf("Color map is too wide - %d\n", cwid);
329
        return 0;
330
    }
331
 
332
    for (i = 0;  i < 256;  i++) {
333
#ifdef HORRIBLY_SLOW_COLOR_MAPPING
334
        cmap[i][0] = 0;  cmap[i][1] = 0;
335
#else
336
        cmap[i][0] = 0;  cmap[i][1] = 0;  cmap[i][2] = 0;
337
#endif
338
    }
339
    color_index = 0;
340
    for (i = 0;  i < nclrs;  i++) {
341
        cp = xpm[i+1];
342
#ifdef HORRIBLY_SLOW_COLOR_MAPPING
343
        for (j = 0;  j < cwid;  j++) {
344
            cmap[color_index][j] = cp[j];
345
        }
346
#else
347
        if (cwid == 1) {
348
            cmap_col = 0;
349
        } else {
350
            for (cmap_col = 0;  cmap_col < 3;  cmap_col++) {
351
                if (cp[1] == std_cmap[cmap_col]) {
352
                    break;
353
                }
354
            }
355
        }
356
        cmap_row = *cp;
357
        cmap[cmap_row][cmap_col] = color_index;
358
#endif
359
        parse_color(cp+cwid, &red, &green, &blue);
360
//        diag_printf("Color[%d] = %02x/%02x/%02x\n", color_index, red, green, blue);
361
        vga_set_cmap(vga.ctlr, color_index+2, red, green, blue);
362
        color_index++;
363
    }
364
 
365
#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP
366
    offset = screen_pos;
367
#else
368
    offset = screen_pos-nrows;
369
#endif
370
    for (row = 0;  row < nrows;  row++) {
371
        cp = xpm[nclrs+1+row];
372
        for (col = 0;  col < ncols;  col++) {
373
#ifdef HORRIBLY_SLOW_COLOR_MAPPING
374
            // Horrible, but portable, way to map colors
375
            for (color_index = 0;  color_index < nclrs;  color_index++) {
376
                color_match = true;
377
                for (j = 0;  j < cwid;  j++) {
378
                    if (cmap[color_index][j] != cp[j]) {
379
                        color_match = false;
380
                    }
381
                }
382
                if (color_match) {
383
                    break;
384
                }
385
            }
386
#else
387
            if (cwid == 1) {
388
                cmap_col = 0;
389
            } else {
390
                for (cmap_col = 0;  cmap_col < 3;  cmap_col++) {
391
                    if (cp[1] == std_cmap[cmap_col]) {
392
                        break;
393
                    }
394
                }
395
            }
396
            cmap_row = *cp;
397
            color_index = cmap[cmap_row][cmap_col];
398
#endif
399
            set_pixel(row+offset, col, color_index+2);
400
            cp += cwid;
401
        }
402
    }
403
#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP
404
    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;
405
    screen_end = VGA_HEIGHT/FONT_HEIGHT;
406
    return offset+nrows;
407
#else    
408
    screen_start = 0;
409
    screen_height = offset / FONT_HEIGHT;
410
    screen_end = screen_height;
411
    return offset;
412
#endif
413
}
414
#endif
415
 
416
void
417
vga_screen_clear(void)
418
{
419
    int row, col;
420
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
421
    int pos;
422
#endif
423
 
424
    for (row = 0;  row < screen_height;  row++) {
425
        for (col = 0;  col < screen_width;  col++) {
426
            screen[row][col] = ' ';
427
            vga_drawc(' ', col, row);
428
        }
429
    }
430
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
431
    // Note: Row 0 seems to wrap incorrectly
432
#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP
433
    pos = 0;
434
#else
435
    pos = (VGA_HEIGHT-1);
436
#endif
437
    show_xpm(banner_xpm, pos);
438
#endif // CYGOPT_UE250_VGA_COMM_LOGO
439
    curX = 0;  curY = screen_start;
440
    if (cursor_enable) {
441
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
442
    }
443
}
444
 
445
// Position cursor
446
void
447
vga_moveto(int X, int Y)
448
{
449
    if (cursor_enable) {
450
        vga_drawc(screen[curY][curX], curX-screen_pan, curY);
451
    }
452
    if (X < 0) X = 0;
453
    if (X >= screen_width) X = screen_width-1;
454
    curX = X;
455
    if (Y < screen_start) Y = screen_start;
456
    if (Y >= screen_height) Y = screen_height-1;
457
    curY = Y;
458
    if (cursor_enable) {
459
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
460
    }
461
}
462
 
463
static unsigned long _bitmap[] = {
464
#ifdef FONT_LEFT_TO_RIGHT
465
    0x00000000, 0x01000000, 0x00010000, 0x01010000,
466
    0x00000100, 0x01000100, 0x00010100, 0x01010100,
467
    0x00000001, 0x01000001, 0x00010001, 0x01010001,
468
    0x00000101, 0x01000101, 0x00010101, 0x01010101,
469
#else
470
    0x00000000, 0x00000001, 0x00000100, 0x00000101,
471
    0x00010000, 0x00010001, 0x00010100, 0x00010101,
472
    0x01000000, 0x01000001, 0x01000100, 0x01000101,
473
    0x01010000, 0x01010001, 0x01010100, 0x01010101
474
#endif
475
};
476
 
477
// Render a character at position (X,Y) with current background/foreground
478
static void
479
vga_drawc(cyg_uint8 c, int x, int y)
480
{
481
    cyg_uint8 bits;
482
    int l, p;
483
    int xoff, yoff;
484
    unsigned long *pix;
485
 
486
    if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) ||
487
        (y < 0) || (y >= screen_height)) return;
488
    for (l = 0;  l < FONT_HEIGHT;  l++) {
489
        bits = font_table[c-FIRST_CHAR][l];
490
        yoff = y*FONT_HEIGHT + l;
491
        xoff = x*FONT_WIDTH;
492
#if 0  // Render font characters one bit at a time
493
        for (p = 0;  p < FONT_WIDTH;  p++) {
494
#ifdef FONT_LEFT_TO_RIGHT
495
            set_pixel(yoff, xoff + p, (bits & 0x80) ? fg : bg);
496
            bits <<= 1;
497
#else
498
            set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg);
499
            bits >>= 1;
500
#endif
501
        }
502
#else  // Render characters 4 bits at a time
503
        pix = (unsigned long *)vga_fb(yoff, xoff);
504
#ifdef FONT_LEFT_TO_RIGHT
505
        *pix++ = _bitmap[(bits & 0xF0) >> 4];
506
        *pix++ = _bitmap[(bits & 0x0F)];
507
#else
508
        *pix++ = _bitmap[(bits & 0x0F)];
509
        *pix++ = _bitmap[(bits & 0xF0) >> 4];
510
#endif
511
#endif
512
    }
513
}
514
 
515
static void
516
vga_refresh(void)
517
{
518
    int row, col;
519
 
520
    for (row = screen_start;  row < screen_height;  row++) {
521
        for (col = 0;  col < VISIBLE_SCREEN_WIDTH;  col++) {
522
            if ((col+screen_pan) < screen_width) {
523
                vga_drawc(screen[row][col+screen_pan], col, row);
524
            } else {
525
                vga_drawc(' ', col, row);
526
            }
527
        }
528
    }
529
    if (cursor_enable) {
530
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
531
    }
532
}
533
 
534
static void
535
vga_scroll(void)
536
{
537
    int col;
538
    cyg_uint8 *c1;
539
    cyg_uint32 *lc0, *lc1, *lcn;
540
    cyg_uint32 *fb_row0, *fb_row1, *fb_rown;
541
 
542
    // First scroll up the virtual screen
543
#if ((SCREEN_WIDTH%4) != 0)
544
#error Scroll code optimized for screen with multiple of 4 columns
545
#endif
546
    lc0 = (cyg_uint32 *)&screen[0][0];
547
    lc1 = (cyg_uint32 *)&screen[1][0];
548
    lcn = (cyg_uint32 *)&screen[screen_height][0];
549
    while (lc1 != lcn) {
550
        *lc0++ = *lc1++;
551
    }
552
    c1 = &screen[screen_height-1][0];
553
    for (col = 0;  col < screen_width;  col++) {
554
        *c1++ = 0x20;
555
    }
556
#if 0  // Scrolling like this is *relly* slow
557
    fb_row0 = (cyg_uint32 *)vga_fb(screen_start*FONT_HEIGHT, 0);
558
    fb_row1 = (cyg_uint32 *)vga_fb((screen_start+1)*FONT_HEIGHT, 0);
559
    fb_rown = (cyg_uint32 *)vga_fb(screen_end*FONT_HEIGHT, 0);
560
#if 0
561
    while (fb_row1 != fb_rown) {
562
        *fb_row0++ = *fb_row1++;
563
    }
564
#else
565
    // Optimized ARM assembly "move" code
566
    asm __volatile(
567
        "mov r0,%0;"
568
        "mov r1,%1;"
569
        "mov r2,%2;"
570
        "10: ldmia r1!,{r3-r6};"
571
        "stmia r0!,{r3-r6};"
572
        "ldmia r1!,{r3-r6};"
573
        "stmia r0!,{r3-r6};"
574
        "cmp r1,r2;"
575
        "bne 10b"
576
        :
577
        : "r"(fb_row0), "r"(fb_row1), "r"(fb_rown)
578
        : "r0","r1","r2","r3","r4","r5","r6"
579
        );
580
#endif
581
    // Erase bottom line
582
    for (col = 0;  col < screen_width;  col++) {
583
        vga_drawc(' ', col, screen_end-1);
584
    }
585
#else  // Clear & redraw is faster!
586
    vga_refresh();
587
#endif
588
}
589
 
590
// Draw one character at the current position
591
void
592
vga_putc(cyg_uint8 c)
593
{
594
    if (cursor_enable) {
595
        vga_drawc(screen[curY][curX], curX-screen_pan, curY);
596
    }
597
    switch (c) {
598
    case '\r':
599
        curX = 0;
600
        break;
601
    case '\n':
602
        curY++;
603
        break;
604
    case '\b':
605
        curX--;
606
        if (curX < 0) {
607
            curY--;
608
            if (curY < 0) curY = 0;
609
            curX = screen_width-1;
610
        }
611
        break;
612
    default:
613
        if (((int)c < FIRST_CHAR) || ((int)c > LAST_CHAR)) c = '.';
614
        screen[curY][curX] = c;
615
        vga_drawc(c, curX-screen_pan, curY);
616
        curX++;
617
        if (curX == screen_width) {
618
            curY++;
619
            curX = 0;
620
        }
621
    }
622
    if (curY >= screen_height) {
623
        vga_scroll();
624
        curY = (screen_height-1);
625
    }
626
    if (cursor_enable) {
627
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
628
    }
629
}
630
 
631
// Basic VGA 'printf()' support
632
 
633
#include <stdarg.h>
634
 
635
#define is_digit(c) ((c >= '0') && (c <= '9'))
636
 
637
static int
638
_cvt(unsigned long val, char *buf, long radix, char *digits)
639
{
640
    char temp[80];
641
    char *cp = temp;
642
    int length = 0;
643
 
644
    if (val == 0) {
645
        /* Special case */
646
        *cp++ = '0';
647
    } else {
648
        while (val) {
649
            *cp++ = digits[val % radix];
650
            val /= radix;
651
        }
652
    }
653
    while (cp != temp) {
654
        *buf++ = *--cp;
655
        length++;
656
    }
657
    *buf = '\0';
658
    return (length);
659
}
660
 
661
static int
662
vga_vprintf(void (*putc)(cyg_uint8), const char *fmt0, va_list ap)
663
{
664
    char c, sign, *cp;
665
    int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
666
    char buf[32];
667
    long val;
668
 
669
    while ((c = *fmt0++)) {
670
        cp = buf;
671
        length = 0;
672
        if (c == '%') {
673
            c = *fmt0++;
674
            left_prec = right_prec = pad_on_right = 0;
675
            if (c == '-') {
676
                c = *fmt0++;
677
                pad_on_right++;
678
            }
679
            if (c == '0') {
680
                zero_fill = TRUE;
681
                c = *fmt0++;
682
            } else {
683
                zero_fill = FALSE;
684
            }
685
            while (is_digit(c)) {
686
                left_prec = (left_prec * 10) + (c - '0');
687
                c = *fmt0++;
688
            }
689
            if (c == '.') {
690
                c = *fmt0++;
691
                zero_fill++;
692
                while (is_digit(c)) {
693
                    right_prec = (right_prec * 10) + (c - '0');
694
                    c = *fmt0++;
695
                }
696
            } else {
697
                right_prec = left_prec;
698
            }
699
            sign = '\0';
700
            switch (c) {
701
            case 'd':
702
            case 'x':
703
            case 'X':
704
                val = va_arg(ap, long);
705
                switch (c) {
706
                case 'd':
707
                    if (val < 0) {
708
                        sign = '-';
709
                        val = -val;
710
                    }
711
                    length = _cvt(val, buf, 10, "0123456789");
712
                    break;
713
                case 'x':
714
                    length = _cvt(val, buf, 16, "0123456789abcdef");
715
                    break;
716
                case 'X':
717
                    length = _cvt(val, buf, 16, "0123456789ABCDEF");
718
                    break;
719
                }
720
                break;
721
            case 's':
722
                cp = va_arg(ap, char *);
723
                length = strlen(cp);
724
                break;
725
            case 'c':
726
                c = va_arg(ap, long /*char*/);
727
                (*putc)(c);
728
                continue;
729
            default:
730
                (*putc)('?');
731
            }
732
            pad = left_prec - length;
733
            if (sign != '\0') {
734
                pad--;
735
            }
736
            if (zero_fill) {
737
                c = '0';
738
                if (sign != '\0') {
739
                    (*putc)(sign);
740
                    sign = '\0';
741
                }
742
            } else {
743
                c = ' ';
744
            }
745
            if (!pad_on_right) {
746
                while (pad-- > 0) {
747
                    (*putc)(c);
748
                }
749
            }
750
            if (sign != '\0') {
751
                (*putc)(sign);
752
            }
753
            while (length-- > 0) {
754
                (*putc)(c = *cp++);
755
                if (c == '\n') {
756
                    (*putc)('\r');
757
                }
758
            }
759
            if (pad_on_right) {
760
                while (pad-- > 0) {
761
                    (*putc)(' ');
762
                }
763
            }
764
        } else {
765
            (*putc)(c);
766
            if (c == '\n') {
767
                (*putc)('\r');
768
            }
769
        }
770
    }
771
 
772
    // FIXME
773
    return 0;
774
}
775
 
776
int
777
_vga_printf(char const *fmt, ...)
778
{
779
    int ret;
780
    va_list ap;
781
 
782
    va_start(ap, fmt);
783
    ret = vga_vprintf(vga_putc, fmt, ap);
784
    va_end(ap);
785
    return (ret);
786
}
787
 
788
//
789
// Support VGA/keyboard (PS2) as a virtual I/O channel
790
//   Adapted from i386/pcmb_screen.c
791
//
792
 
793
 
794
//-----------------------------------------------------------------------------
795
// Keyboard definitions
796
 
797
#define KBDATAPORT      0x0060          // data I/O port
798
#define KBCMDPORT       0x0064          // command port (write)
799
#define KBSTATPORT      0x0064          // status port  (read)
800
 
801
#define KBINRDY         0x01
802
#define KBOUTRDY        0x02
803
#define KBTXTO          0x40          // Transmit timeout - nothing there
804
#define KBTEST          0xAB
805
 
806
// Scan codes
807
 
808
#define LSHIFT    0x2a
809
#define RSHIFT    0x36
810
#define CTRL      0x1d
811
#define ALT       0x38
812
#define CAPS      0x3a
813
#define NUMS      0x45
814
 
815
#define BREAK     0x80
816
 
817
// Bits for KBFlags
818
 
819
#define KBNormal  0x0000
820
#define KBShift   0x0001
821
#define KBCtrl    0x0002
822
#define KBAlt     0x0004
823
#define KBIndex   0x0007  // mask for the above
824
 
825
#define KBExtend   0x0010
826
#define KBAck      0x0020
827
#define KBResend   0x0040
828
#define KBShiftL   (0x0080 | KBShift)
829
#define KBShiftR   (0x0100 | KBShift)
830
#define KBCtrlL    (0x0200 | KBCtrl)
831
#define KBCtrlR    (0x0400 | KBCtrl)
832
#define KBAltL     (0x0800 | KBAlt)
833
#define KBAltR     (0x1000 | KBAlt)
834
#define KBCapsLock 0x2000
835
#define KBNumLock  0x4000
836
 
837
#define KBArrowUp       0x48
838
#define KBArrowRight    0x4D
839
#define KBArrowLeft     0x4B
840
#define KBArrowDown     0x50
841
 
842
//-----------------------------------------------------------------------------
843
// Keyboard Variables
844
 
845
static  int  KBFlags = 0;
846
 
847
static  CYG_BYTE  KBPending = 0xFF;
848
 
849
static  CYG_BYTE  KBScanTable[128][4] = {
850
//  Normal    Shift    Control    Alt
851
// 0x00
852
    {  0xFF,    0xFF,    0xFF,    0xFF,   },
853
    {  0x1b,    0x1b,    0x1b,    0xFF,  },
854
    {  '1',    '!',    0xFF,    0xFF,  },
855
    {  '2',    '"',    0xFF,    0xFF,  },
856
    {  '3',    '#',    0xFF,    0xFF,  },
857
    {  '4',    '$',    0xFF,    0xFF,  },
858
    {  '5',    '%',    0xFF,    0xFF,  },
859
    {  '6',    '^',    0xFF,    0xFF,  },
860
    {  '7',    '&',    0xFF,    0xFF,  },
861
    {  '8',    '*',    0xFF,    0xFF,  },
862
    {  '9',    '(',    0xFF,    0xFF,  },
863
    {  '0',    ')',    0xFF,    0xFF,  },
864
    {  '-',    '_',    0xFF,    0xFF,  },
865
    {  '=',    '+',    0xFF,    0xFF,  },
866
    {  '\b',    '\b',    0xFF,    0xFF,  },
867
    {  '\t',    '\t',    0xFF,    0xFF,  },
868
// 0x10
869
    {  'q',    'Q',    0x11,    0xFF,  },
870
    {  'w',    'W',    0x17,    0xFF,  },
871
    {  'e',    'E',    0x05,    0xFF,  },
872
    {  'r',    'R',    0x12,    0xFF,  },
873
    {  't',    'T',    0x14,    0xFF,  },
874
    {  'y',    'Y',    0x19,    0xFF,  },
875
    {  'u',    'U',    0x15,    0xFF,  },
876
    {  'i',    'I',    0x09,    0xFF,  },
877
    {  'o',    'O',    0x0F,    0xFF,  },
878
    {  'p',    'P',    0x10,    0xFF,  },
879
    {  '[',    '{',    0x1b,    0xFF,  },
880
    {  ']',    '}',    0x1d,    0xFF,  },
881
    {  '\r',    '\r',    '\n',    0xFF,  },
882
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
883
    {  'a',    'A',    0x01,    0xFF,  },
884
    {  's',    'S',    0x13,    0xFF,  },
885
// 0x20
886
    {  'd',    'D',    0x04,    0xFF,  },
887
    {  'f',    'F',    0x06,    0xFF,  },
888
    {  'g',    'G',    0x07,    0xFF,  },
889
    {  'h',    'H',    0x08,    0xFF,  },
890
    {  'j',    'J',    0x0a,    0xFF,  },
891
    {  'k',    'K',    0x0b,    0xFF,  },
892
    {  'l',    'L',    0x0c,    0xFF,  },
893
    {  ';',    ':',    0xFF,    0xFF,  },
894
    {  0x27,    '@',    0xFF,    0xFF,  },
895
    {  '#',    '~',    0xFF,    0xFF,  },
896
    {  '`',    '~',    0xFF,    0xFF,  },
897
    {  '\\',    '|',    0x1C,    0xFF,  },
898
    {  'z',    'Z',    0x1A,    0xFF,  },
899
    {  'x',    'X',    0x18,    0xFF,  },
900
    {  'c',    'C',    0x03,    0xFF,  },
901
    {  'v',    'V',    0x16,    0xFF,  },
902
// 0x30
903
    {  'b',    'B',    0x02,    0xFF,  },
904
    {  'n',    'N',    0x0E,    0xFF,  },
905
    {  'm',    'M',    0x0D,    0xFF,  },
906
    {  ',',    '<',    0xFF,    0xFF,  },
907
    {  '.',    '>',    0xFF,    0xFF,  },
908
    {  '/',    '?',    0xFF,    0xFF,  },
909
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
910
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
911
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
912
    {  ' ',    ' ',    ' ',    ' ',  },
913
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
914
    {  0xF1,    0xE1,    0xFF,    0xFF,  },
915
    {  0xF2,    0xE2,    0xFF,    0xFF,  },
916
    {  0xF3,    0xE3,    0xFF,    0xFF,  },
917
    {  0xF4,    0xE4,    0xFF,    0xFF,  },
918
    {  0xF5,    0xE5,    0xFF,    0xFF,  },
919
// 0x40
920
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
921
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
922
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
923
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
924
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
925
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
926
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
927
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
928
 
929
    {  0x15,    0x15,    0x15,    0x15,  },
930
    {  0x10,    0x10,    0x10,    0x10,  },
931
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
932
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
933
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
934
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
935
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
936
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
937
// 0x50
938
    {  0x04,    0x04,    0x04,    0x04,  },
939
    {  0x0e,    0x0e,    0x0e,    0x0e,  },
940
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
941
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
942
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
943
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
944
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
945
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
946
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
947
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
948
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
949
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
950
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
951
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
952
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
953
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
954
// 0x60
955
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
956
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
957
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
958
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
959
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
960
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
961
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
962
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
963
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
964
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
965
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
966
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
967
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
968
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
969
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
970
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
971
// 0x70
972
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
973
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
974
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
975
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
976
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
977
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
978
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
979
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
980
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
981
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
982
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
983
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
984
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
985
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
986
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
987
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
988
};
989
 
990
static int KBIndexTab[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
991
 
992
//-----------------------------------------------------------------------------
993
 
994
static __inline__ cyg_uint8
995
inb(cyg_uint32 port)
996
{
997
    cyg_uint8 val;
998
    val = localbus_readl(port<<2);
999
    return val;
1000
}
1001
 
1002
static __inline__ void
1003
outb(cyg_uint32 port, cyg_uint8 val)
1004
{
1005
    localbus_writel(val, port<<2);
1006
}
1007
 
1008
static cyg_bool
1009
KeyboardInit(void)
1010
{
1011
    unsigned char c, s;
1012
 
1013
    /* flush input queue */
1014
    while ((inb(KBSTATPORT) & KBINRDY)) {
1015
        (void)inb(KBDATAPORT);
1016
    }
1017
 
1018
    /* Send self-test - controller local */
1019
    while (inb(KBSTATPORT) & KBOUTRDY) c = inb(KBDATAPORT);
1020
    outb(KBCMDPORT,0xAA);
1021
    while ((inb(KBSTATPORT) & KBINRDY) == 0) ; /* wait input ready */
1022
    if ((c = inb(KBDATAPORT)) != 0x55) {
1023
#ifdef DEBUG_KBD_INIT
1024
        diag_printf("Keyboard self test failed - result: %x\n", c);
1025
#endif
1026
        return false;
1027
    }
1028
 
1029
    /* Enable interrupts and keyboard controller */
1030
    while (inb(KBSTATPORT) & KBOUTRDY) ;
1031
    outb(KBCMDPORT,0x60);
1032
    while (inb(KBSTATPORT) & KBOUTRDY) ;
1033
    outb(KBCMDPORT,0x45);
1034
    CYGACC_CALL_IF_DELAY_US(10000);  // 10ms
1035
 
1036
    while (inb(KBSTATPORT) & KBOUTRDY) ;
1037
    outb(KBCMDPORT,0xAE);  // Enable keyboard
1038
 
1039
    /* See if a keyboard is connected */
1040
    while (inb(KBSTATPORT) & KBOUTRDY) ;
1041
    outb(KBDATAPORT,0xFF);
1042
    while (((s = inb(KBSTATPORT)) & (KBINRDY|KBTXTO)) == 0) ; /* wait input ready */
1043
    if ((s & KBTXTO) || ((c = inb(KBDATAPORT)) != 0xFA)) {
1044
#ifdef DEBUG_KBD_INIT
1045
        diag_printf("Keyboard reset failed - no ACK: %x, stat: %x\n", c, s);
1046
#endif
1047
        return false;
1048
    }
1049
    while (((s = inb(KBSTATPORT)) & KBINRDY) == 0) ; /* wait input ready */
1050
    if ((s & KBTXTO) || ((c = inb(KBDATAPORT)) != 0xAA)) {
1051
#ifdef DEBUG_KBD_INIT
1052
        diag_printf("Keyboard reset failed - bad code: %x, stat: %x\n", c, s);
1053
#endif
1054
        return false;
1055
    }
1056
 
1057
    // Set scan mode
1058
    while (inb(KBSTATPORT) & KBOUTRDY) ;
1059
    outb(KBCMDPORT,0x20);
1060
    while ((inb(KBSTATPORT) & KBINRDY) == 0) ; /* wait input ready */
1061
    if (! (inb(KBDATAPORT) & 0x40)) {
1062
        /*
1063
         * Quote from PS/2 System Reference Manual:
1064
         *
1065
         * "Address hex 0060 and address hex 0064 should be
1066
         * written only when the input-buffer-full bit and
1067
         * output-buffer-full bit in the Controller Status
1068
         * register are set 0." (KBINRDY and KBOUTRDY)
1069
         */
1070
 
1071
        while (inb(KBSTATPORT) & (KBINRDY | KBOUTRDY)) ;
1072
        outb(KBDATAPORT,0xF0);
1073
        while (inb(KBSTATPORT) & (KBINRDY | KBOUTRDY)) ;
1074
        outb(KBDATAPORT,0x01);
1075
    }
1076
 
1077
    KBFlags = 0;
1078
    return true;
1079
} /* KeyboardInit */
1080
 
1081
//-----------------------------------------------------------------------------
1082
 
1083
static CYG_BYTE
1084
KeyboardAscii(CYG_BYTE scancode)
1085
{
1086
    CYG_BYTE ascii = 0xFF;
1087
 
1088
    // Start by handling all shift/ctl keys:
1089
 
1090
    switch( scancode ) {
1091
    case 0xe0:
1092
        KBFlags |= KBExtend;
1093
        return 0xFF;
1094
 
1095
    case 0xfa:
1096
        KBFlags |= KBAck;
1097
        return 0xFF;
1098
 
1099
    case 0xfe:
1100
        KBFlags |= KBResend;
1101
        return 0xFF;
1102
 
1103
    case LSHIFT:
1104
        KBFlags |= KBShiftL;
1105
        return 0xFF;
1106
 
1107
    case LSHIFT | BREAK:
1108
        KBFlags &= ~KBShiftL;
1109
        return 0xFF;
1110
 
1111
    case RSHIFT:
1112
        KBFlags |= KBShiftR;
1113
        return 0xFF;
1114
 
1115
    case RSHIFT | BREAK:
1116
        KBFlags &= ~KBShiftR;
1117
        return 0xFF;
1118
 
1119
    case CTRL:
1120
        if( KBFlags & KBExtend )
1121
        {
1122
            KBFlags |= KBCtrlR;
1123
            KBFlags &= ~KBExtend;
1124
        }
1125
        else  KBFlags |= KBCtrlL;
1126
        return 0xFF;
1127
 
1128
    case CTRL | BREAK:
1129
        if( KBFlags & KBExtend )
1130
        {
1131
            KBFlags &= ~KBCtrlR;
1132
            KBFlags &= ~KBExtend;
1133
        }
1134
        else  KBFlags &= ~KBCtrlL;
1135
        return 0xFF;
1136
 
1137
 
1138
    case ALT:
1139
        if( KBFlags & KBExtend )
1140
        {
1141
            KBFlags |= KBAltR;
1142
            KBFlags &= ~KBExtend;
1143
        }
1144
        else  KBFlags |= KBAltL;
1145
        return 0xFF;
1146
 
1147
    case ALT | BREAK:
1148
        if( KBFlags & KBExtend )
1149
        {
1150
            KBFlags &= ~KBAltR;
1151
            KBFlags &= ~KBExtend;
1152
        }
1153
        else  KBFlags &= ~KBAltL;
1154
        return 0xFF;
1155
 
1156
    case CAPS:
1157
        KBFlags ^= KBCapsLock;
1158
    case CAPS | BREAK:
1159
        return 0xFF;
1160
 
1161
    case NUMS:
1162
        KBFlags ^= KBNumLock;
1163
    case NUMS | BREAK:
1164
        return 0xFF;
1165
 
1166
    case KBArrowUp:
1167
    case KBArrowDown:
1168
        screen_pan = 0;
1169
        vga_refresh();
1170
        break;
1171
    case KBArrowLeft:
1172
        screen_pan -= SCREEN_PAN;
1173
        if (screen_pan < 0) screen_pan = 0;
1174
        vga_refresh();
1175
        break;
1176
    case KBArrowRight:
1177
        screen_pan += SCREEN_PAN;
1178
        if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN))
1179
            screen_pan = SCREEN_WIDTH-SCREEN_PAN;
1180
        vga_refresh();
1181
        break;
1182
 
1183
    }
1184
 
1185
    // Clear Extend flag if set
1186
    KBFlags &= ~KBExtend;
1187
 
1188
    // Ignore all other BREAK codes
1189
    if( scancode & 0x80 ) return 0xFF;
1190
 
1191
    // Here the scancode is for something we can turn
1192
    // into an ASCII value
1193
 
1194
    ascii = KBScanTable[scancode & 0x7F][KBIndexTab[KBFlags & KBIndex]];
1195
 
1196
    return ascii;
1197
 
1198
} /* KeyboardAscii */
1199
 
1200
//-----------------------------------------------------------------------------
1201
 
1202
static int
1203
KeyboardTest(void)
1204
{
1205
    // If there is a pending character, return True
1206
    if( KBPending != 0xFF ) return true;
1207
 
1208
    // If there is something waiting at the port, get it
1209
    for(;;) {
1210
        CYG_BYTE stat, code;
1211
        CYG_BYTE c;
1212
 
1213
        stat = inb(KBSTATPORT);
1214
 
1215
        if( (stat & KBINRDY) == 0 )
1216
            break;
1217
 
1218
        code = inb(KBDATAPORT);
1219
 
1220
        // Translate to ASCII
1221
        c = KeyboardAscii(code);
1222
 
1223
        // if it is a real ASCII char, save it and
1224
        // return True.
1225
        if( c != 0xFF ) {
1226
            KBPending = c;
1227
            return true;
1228
        }
1229
    }
1230
 
1231
    // Otherwise return False
1232
    return false;
1233
 
1234
} /* KeyboardTest */
1235
 
1236
char
1237
KeyboardChar(void)
1238
{
1239
    char c = KBPending;
1240
    KBPending = 0xFF;
1241
    return c;
1242
}
1243
 
1244
static int  _timeout = 500;
1245
 
1246
static cyg_bool
1247
vga_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
1248
{
1249
    if( !KeyboardTest() )
1250
        return false;
1251
    *ch = KBPending;
1252
    KBPending = 0xFF;
1253
    return true;
1254
}
1255
 
1256
static cyg_uint8
1257
vga_comm_getc(void* __ch_data)
1258
{
1259
    cyg_uint8 ch;
1260
 
1261
    while (!vga_comm_getc_nonblock(__ch_data, &ch)) ;
1262
    return ch;
1263
}
1264
 
1265
static void
1266
vga_comm_putc(void* __ch_data, cyg_uint8 c)
1267
{
1268
    vga_putc(c);
1269
}
1270
 
1271
static void
1272
vga_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
1273
{
1274
#if 0
1275
    CYGARC_HAL_SAVE_GP();
1276
 
1277
    while(__len-- > 0)
1278
        vga_comm_putc(__ch_data, *__buf++);
1279
 
1280
    CYGARC_HAL_RESTORE_GP();
1281
#endif
1282
}
1283
 
1284
static void
1285
vga_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
1286
{
1287
#if 0
1288
    CYGARC_HAL_SAVE_GP();
1289
 
1290
    while(__len-- > 0)
1291
        *__buf++ = vga_comm_getc(__ch_data);
1292
 
1293
    CYGARC_HAL_RESTORE_GP();
1294
#endif
1295
}
1296
 
1297
static cyg_bool
1298
vga_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
1299
{
1300
    int delay_count;
1301
    cyg_bool res;
1302
 
1303
    delay_count = _timeout * 2; // delay in .5 ms steps
1304
    for(;;) {
1305
        res = vga_comm_getc_nonblock(__ch_data, ch);
1306
        if (res || 0 == delay_count--)
1307
            break;
1308
        CYGACC_CALL_IF_DELAY_US(500);
1309
    }
1310
    return res;
1311
}
1312
 
1313
static int
1314
vga_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
1315
{
1316
    static int vector = 0;
1317
    int ret = -1;
1318
    static int irq_state = 0;
1319
 
1320
    CYGARC_HAL_SAVE_GP();
1321
 
1322
    switch (__func) {
1323
    case __COMMCTL_IRQ_ENABLE:
1324
        ret = irq_state;
1325
        irq_state = 1;
1326
        break;
1327
    case __COMMCTL_IRQ_DISABLE:
1328
        ret = irq_state;
1329
        irq_state = 0;
1330
        break;
1331
    case __COMMCTL_DBG_ISR_VECTOR:
1332
        ret = vector;
1333
        break;
1334
    case __COMMCTL_SET_TIMEOUT:
1335
    {
1336
        va_list ap;
1337
 
1338
        va_start(ap, __func);
1339
 
1340
        ret = _timeout;
1341
        _timeout = va_arg(ap, cyg_uint32);
1342
 
1343
        va_end(ap);
1344
        break;
1345
    }
1346
    case __COMMCTL_FLUSH_OUTPUT:
1347
        ret = 0;
1348
        break;
1349
    default:
1350
        break;
1351
    }
1352
    CYGARC_HAL_RESTORE_GP();
1353
    return ret;
1354
}
1355
 
1356
static int
1357
vga_comm_isr(void *__ch_data, int* __ctrlc,
1358
           CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
1359
{
1360
#if 0
1361
    char ch;
1362
 
1363
    cyg_drv_interrupt_acknowledge(__vector);
1364
    *__ctrlc = 0;
1365
    if (vga_comm_getc_nonblock(__ch_data, &ch)) {
1366
        if (ch == 0x03) {
1367
            *__ctrlc = 1;
1368
        }
1369
    }
1370
    return CYG_ISR_HANDLED;
1371
#else
1372
    return 0;
1373
#endif
1374
}
1375
 
1376
void
1377
vga_comm_init(cyg_uint32 *addr)
1378
{
1379
    static int init = 0;
1380
 
1381
    if (!init) {
1382
        hal_virtual_comm_table_t* comm;
1383
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
1384
 
1385
        init = 1;
1386
        if (!KeyboardInit()) {
1387
            // No keyboard - no VGA/CRT display
1388
            return;
1389
        }
1390
 
1391
        // Initialize screen
1392
        cursor_enable = true;
1393
        vga_init(addr);
1394
        vga_on(true);
1395
        vga_screen_clear();
1396
 
1397
        // Setup procs in the vector table
1398
        CYGACC_CALL_IF_SET_CONSOLE_COMM(1);  // FIXME - should be controlled by CDL
1399
        comm = CYGACC_CALL_IF_CONSOLE_PROCS();
1400
        //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
1401
        CYGACC_COMM_IF_WRITE_SET(*comm, vga_comm_write);
1402
        CYGACC_COMM_IF_READ_SET(*comm, vga_comm_read);
1403
        CYGACC_COMM_IF_PUTC_SET(*comm, vga_comm_putc);
1404
        CYGACC_COMM_IF_GETC_SET(*comm, vga_comm_getc);
1405
        CYGACC_COMM_IF_CONTROL_SET(*comm, vga_comm_control);
1406
        CYGACC_COMM_IF_DBG_ISR_SET(*comm, vga_comm_isr);
1407
        CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, vga_comm_getc_timeout);
1408
 
1409
        // Restore original console
1410
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
1411
    }
1412
}
1413
 
1414
#ifdef CYGPKG_REDBOOT
1415
#include <redboot.h>
1416
 
1417
// Get here when RedBoot is idle.  If it's been long enough, then
1418
// dim the VGA.  The problem is - how to determine other activities
1419
// so at this doesn't get in the way.  In the default case, this will
1420
// be called from RedBoot every 10ms (CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT)
1421
 
1422
#define MAX_IDLE_TIME (30*100)
1423
 
1424
static void
1425
idle(bool is_idle)
1426
{
1427
    static int idle_time = 0;
1428
    static bool was_idled = false;
1429
 
1430
    if (is_idle) {
1431
        if (!was_idled) {
1432
            if (++idle_time == MAX_IDLE_TIME) {
1433
                was_idled = true;
1434
                vga_on(false);
1435
            }
1436
        }
1437
    } else {
1438
        idle_time = 0;
1439
        if (was_idled) {
1440
            was_idled = false;
1441
                vga_on(true);
1442
        }
1443
    }
1444
}
1445
 
1446
RedBoot_idle(idle, RedBoot_AFTER_NETIO);
1447
#endif
1448
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.