root/Whitix/trunk/video/console.c

Revision 1964, 18.4 KB (checked in by mwhitworth, 3 years ago)

Patch from Kostadin, reset background color when resetting colors.

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <console.h>
20#include <fs/devfs.h>
21#include <fs/vfs.h>
22#include <error.h>
23#include <malloc.h>
24#include <module.h>
25#include <i386/ioports.h>
26#include <task.h>
27#include <fs/icfs.h>
28#include <print.h>
29#include <panic.h>
30#include <keobject.h>
31#include <devices/device.h>
32#include <devices/class.h>
33
34/* Device number */
35#define CONSOLE_MAJOR 1
36
37/* Should all the translating be in userspace? (i.e. should there be a raw option?)
38   Windows and X11 do that already. It can't be in userspace until everything
39   runs graphically */
40
41#define EXT_BASE 0x80
42
43/* Keypad keys */
44#define EXT_UP EXT_BASE+1
45#define EXT_DOWN EXT_BASE+2
46#define EXT_LEFT EXT_BASE+3
47#define EXT_RIGHT EXT_BASE+4
48
49/* Escape key */
50#define EXT_ESC EXT_BASE+5
51
52/* Read settings from a kernel command line soon */
53
54#define CONSOLE_WIDTH   80
55#define CONSOLE_BWIDTH  (CONSOLE_WIDTH*2)
56#define CONSOLE_HEIGHT  25
57#define CONSOLE_BHEIGHT (CONSOLE_HEIGHT*2)
58#define CONSOLE_SIZE    (CONSOLE_WIDTH * CONSOLE_HEIGHT *2)     /* Console size in bytes. */
59#define TAB_WIDTH       8
60#define CLEAR           ((0x07 << 8) | (' '))
61
62#define CONSOLE_BUF(i)  (scrBuf+(CONSOLE_SIZE*(i)))
63#define CONSOLE_IND(i,j) ((j)*CONSOLE_BWIDTH + (i))
64
65static int rows = CONSOLE_HEIGHT, cols = CONSOLE_WIDTH;
66
67static void ConsoleUpdateCursorPos(int console);
68
69static BYTE* screen=(BYTE*)0xC00B8000; /* VGA memory. */
70static BYTE* scrBuf;
71int currConsole=0;
72int numTextConsoles = MAX_CONSOLES;
73struct Console consoles[MAX_CONSOLES];
74Spinlock consoleLock;
75
76/* Keymaps. */
77
78BYTE scanCodes[]={
79        0,EXT_ESC,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t', /* 0x00 - 0x0F */
80        'q','w','e','r','t','y','u','i','o','p','[',']','\n',0,'a','s', /* 0x10 - 0x1F */
81        'd','f','g','h','j','k','l',';','\'',0,0,'#','z','x','c','v', /* 0x20 - 0x2F */
82        'b','n','m',',','.','/',0,0,0,' ',0,0,0,0,0,0, /* 0x30 - 0x3F */
83        0,0,0,0,0,0,0,'7','8','9',0,'4','5','6',0,'1', /* 0x40 - 0x4F */
84        '2','3',0,0,0,0,'\\','4','5','6','7','8','9',0,0,0, /* 0x50 - 0x5F */
85};
86
87SYMBOL_EXPORT(scanCodes);
88
89BYTE shiftScanCodes[]={
90        0,0,'!','"',0xA3,'$','%','^','&','*','(',')','_','+','\b', /* 0x00 - 0x0F */
91        0,'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',0,'A', /* 0x10 - 0x1F */
92        'S','D','F','G','H','J','K','L',':','@',0,0,'~',
93        'Z','X','C','V','B','N','M','<','>','?',0,
94        0,0,
95        ' ',
96        0,0,0,0,0,0,0,0,0,0, /* Function keys */
97        0,0,0,0,0,0,0,0,0,0,0,'1','2','3',0,0,'4','5','|','7','8','9',
98};
99
100SYMBOL_EXPORT(shiftScanCodes);
101
102/* Special characters such as the arrow keys */
103
104char e0ScanCodes[]={
105        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 - 0x0F */
106        0,0,0,0,0,0,0,0,0,0,0,0,'\n',0,0,0, /* 0x10 - 0x1F */
107        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 - 0x2F */
108        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x30 - 0x3F */
109        0,0,0,0,0,0,0,0,EXT_UP,0,0,EXT_LEFT,0,EXT_RIGHT,0,0, /* 0x40 - 0x4F */
110        EXT_DOWN,0,0,0x7F,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 - 0x5F */
111        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x6F */
112        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x70 - 0x7F */
113        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 - 0x8F */
114        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
115        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
116        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
117};
118
119SYMBOL_EXPORT(e0ScanCodes);
120
121static void ConsoleNewLine();
122static void ConsoleUpdateCursorPos();
123static void ConsoleClearScreen();
124static void ConsoleWrite(char c,int index);
125static int ConsoleWriteString(int console,char* str,int length);
126
127int ChangeConsole(int index)
128{
129        if (consoles[index].flags & CONSOLE_GRAPHICS || (currConsole == index))
130                return 0;
131
132        SpinLockIrq(&consoleLock);
133
134        /* Multiple screens are set up during the boot sequence. */
135        if (!scrBuf || index < 0 || index >= MAX_CONSOLES)
136                goto error;
137
138        /* Copy current vga screen memory to scrBuf[currConsole] */
139        memcpy(CONSOLE_BUF(currConsole),screen,CONSOLE_SIZE);
140
141        currConsole=index;
142
143        /* And copy scrBuf[currConsole] into VGA screen memory */
144        memcpy(screen,CONSOLE_BUF(currConsole), CONSOLE_SIZE);
145
146        ConsoleUpdateCursorPos(currConsole);
147
148error:
149        SpinUnlockIrq(&consoleLock);
150        return 0;
151}
152
153SYMBOL_EXPORT(ChangeConsole);
154
155static void ConsoleScrollScreen(int index)
156{
157        int i;
158
159//      if (consoles[index].flags & CONSOLE_GRAPHICS)
160        //      return;
161
162        PreemptDisable();
163 
164        if (currConsole == index)
165        {
166                for (i=0; i < CONSOLE_HEIGHT-1 ; i++)
167                        memcpy ( &screen [ CONSOLE_IND(0,i) ] , &screen [ CONSOLE_IND(0,i+1) ] , CONSOLE_BWIDTH);
168               
169                /* Clear the last line of the console. */
170                memsetw( & screen[ CONSOLE_IND(0,i) ] , CONSOLE_WIDTH, CLEAR);
171        }else{
172                for (i=0; i<CONSOLE_HEIGHT-1; i++)
173                        memcpy ( & CONSOLE_BUF(index) [ CONSOLE_IND(0,i) ] ,
174                                & CONSOLE_BUF(index) [ CONSOLE_IND(0,i) ], CONSOLE_BWIDTH);
175                       
176                /* Clear last line */
177                memsetw( & CONSOLE_BUF(index)[ CONSOLE_IND(0,i) ] , CONSOLE_WIDTH, CLEAR);
178        }
179
180        PreemptEnable();
181}
182
183void putc(int c)
184{
185        ConsoleWrite(c,currConsole);
186}
187
188unsigned char colorTable[] = {0, 4, 2, 6, 1, 5, 3, 7};
189
190/* TODO: Should we use currCons? */
191
192int ConsoleWriteString(int console, char* str, int length)
193{
194        struct Console* currCons=&consoles[console];
195        int oldLength=length;
196
197//      if (currCons->flags & CONSOLE_GRAPHICS)
198//              return 0;
199
200        while (length--)
201        {
202                if (*str == 0x1B)
203                {
204                        currCons->inCtrl=1;
205                        goto end;
206                }
207
208                if (currCons->inCtrl)
209                {
210                        if (*str == '[')
211                        {
212                                currCons->ctrlParams=1;
213                                ZeroMemory(currCons->params, sizeof(unsigned int)*16);
214                                currCons->paramIndex=0;
215                                goto end;
216                        }
217                       
218                        if (currCons->ctrlParams)
219                        {
220                                if (*str == ';')
221                                {
222                                        ++currCons->paramIndex;
223                                        goto end;
224                                }else if (*str < '0' || *str > '9') /* Command */
225                                {
226                                        currCons->cmdLetter=1;
227                                        currCons->ctrlParams=0;
228                                }else{
229                                        currCons->params[currCons->paramIndex]*=10;
230                                        currCons->params[currCons->paramIndex]+=(*str)-'0';
231                                        goto end;
232                                }
233                        }
234
235                        /* VT100 control characters are handled here. */
236                        if (currCons->cmdLetter)
237                        {
238                                switch (*str)
239                                {
240                                        case 'C':
241                                                currCons->currX+=currCons->params[0];
242                                                ConsoleUpdateCursorPos(console);
243                                                break;
244                                               
245                                        case 'D':
246                                                currCons->currX-=currCons->params[0];
247                                                ConsoleUpdateCursorPos(console);
248                                                break;
249                                               
250                                        /* 'J'. Clear the screen. */
251                                        case 'J':
252                                                ConsoleClearScreen(console);
253                                                break;
254
255                                        /* 'H'. Move the cursor to the specified position */
256                                        case 'H':
257                                                /* First parameter is row, second is column. */
258
259                                                /* Bound the given parameters. */
260                                                if (currCons->params[0] >= CONSOLE_HEIGHT)
261                                                        currCons->params[0]=CONSOLE_HEIGHT;
262
263                                                if (currCons->params[1] >= CONSOLE_WIDTH)
264                                                        currCons->params[1]=CONSOLE_WIDTH;
265
266                                                /* Update the cursor position. */
267                                                currCons->currY = currCons->params[0];
268                                                currCons->currX = currCons->params[1];
269                                                ConsoleUpdateCursorPos(console);
270
271                                                break;
272
273                                        /* 'K'. Erase characters from console. */
274                                        case 'K':
275                                        {
276                                                switch (currCons->params[0])
277                                                {
278
279                                                /* From current cursor position to end of line */
280                                                case 0:
281                                                        if (currConsole == console)
282                                                                memsetw((WORD*)(screen+(currCons->currY*(CONSOLE_WIDTH*2))+(currCons->currX*2)),CONSOLE_WIDTH-currCons->currX,(currCons->currColor << 8) | ' ');
283                                                        else
284                                                                memsetw((WORD*)(scrBuf+(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*console)+(currCons->currY*(CONSOLE_WIDTH*2))+currCons->currX),CONSOLE_WIDTH-currCons->currX,(currCons->currColor << 8) | ' ');
285                                                        break;
286
287                                                /* From start of line to current cursor position */
288                                                case 1:
289                                                        if (currConsole == console)
290                                                                memsetw((WORD*)(screen+(currCons->currY*(CONSOLE_WIDTH*2))), currCons->currX,(currCons->currColor << 8) | ' ');
291                                                        else
292                                                                memsetw((WORD*)(scrBuf+(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*console)+(currCons->currY*(CONSOLE_WIDTH*2))), currCons->currX ,(currCons->currColor << 8) | ' ');
293                                                        break;
294
295                                                case 2:
296                                                        /* Erase whole of current line */
297                                                        if (currConsole == console)
298                                                                memsetw((WORD*)(screen+(currCons->currY*(CONSOLE_WIDTH*2))),CONSOLE_WIDTH,(currCons->currColor << 8) | ' ');
299                                                        else
300                                                                memsetw((WORD*)(scrBuf+(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*console)+(currCons->currY*(CONSOLE_WIDTH*2))),CONSOLE_WIDTH,(currCons->currColor << 8) | ' ');
301                                                        break;
302                                                }
303                                                break;
304                                        }
305
306                                        /* 'm'. Set graphic rendition. */
307                                        case 'm':
308                                                switch (currCons->params[0])
309                                                {
310                                                        /* Reset the color */
311                                                        case 0:
312                                                                currCons->foreColor = 7;
313                                                                currCons->backColor = 0;
314                                                                currCons->currColor = currCons->foreColor | (currCons->backColor << 4);
315                                                                break;
316                                                               
317                                                        case 1:
318                                                        case 2:
319                                                                currCons->currColor ^= 0x08;
320                                                                break;
321                                                               
322                                                        /* Invert the color */
323                                                        case 7:
324                                                                currCons->currColor=(currCons->currColor & 0x88) | (((currCons->currColor >> 4) | (currCons->currColor << 4)) & 0x77);                                                         
325                                                                break;
326
327                                                        /* Set the text color */
328                                                        case 30 ... 37:         
329                                                                currCons->foreColor = colorTable[currCons->params[0] % 10];
330                                                                currCons->currColor = currCons->foreColor | (currCons->backColor << 4);
331                                                                break;
332                                                               
333                                                        /* Set the background color */
334                                                        case 40 ... 47:
335                                                                currCons->backColor = colorTable[currCons->params[0] % 10];
336                                                                currCons->currColor = currCons->foreColor | (currCons->backColor << 4);
337                                                                break;
338                                                };
339
340                                                break;
341                                }
342
343                                /* Reset the control variables, in case we get another iteration. */
344                                currCons->inCtrl= currCons->paramIndex = currCons->cmdLetter = 0;
345                                goto end;
346                        }
347                }
348                outb(0xE9, *str);
349                ConsoleWrite(*str, console);
350end:
351                str++;
352        }
353
354        ConsoleUpdateCursorPos(console);
355
356        return oldLength;
357}
358
359SYMBOL_EXPORT(ConsoleWriteString);
360
361extern void KeyboardDoAlarm();
362
363/* Writes an ASCII character to screen */
364
365static void ConsoleWrite(char c,int index)
366{
367        struct Console* cons=&consoles[index];
368
369        if (cons->flags & CONSOLE_GRAPHICS)
370                return;
371
372        switch (c)
373        {
374        case '\r':
375                break;
376
377        case '\n':
378                ConsoleNewLine(index);
379                break;
380       
381        case '\b':
382                if (cons->currX > 0)
383                {
384                        cons->currX--;
385                       
386                        if (currConsole == index)
387                        {
388                                screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)]=' ';
389                                screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+1]=cons->currColor;
390                        }else{
391                                scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)]=' ';
392                                scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+(cons->currY*(CONSOLE_WIDTH*2))+(cons->currY*2)+1]=cons->currColor;
393                        }
394                }
395                break;
396
397        case '\t':
398        {
399                if (currConsole == index)
400                {
401                        int i;
402                        for (i=0; i<TAB_WIDTH*2; i+=2)
403                        {
404                                screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+i]=' ';
405                                screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+1+i]=cons->currColor;
406                                ++cons->currX;
407                                if (cons->currX >= CONSOLE_WIDTH)
408                                        ConsoleNewLine(currConsole);
409                        }
410                }else{
411                        int i;
412                        for (i=0; i<TAB_WIDTH*2; i+=2)
413                        {
414                                scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+i]=' ';
415                                scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+i+1]=cons->currColor;
416                                ++cons->currX;
417                                if (cons->currX >= CONSOLE_WIDTH)
418                                        ConsoleNewLine(index);
419                        }
420                }
421                break;
422        }
423
424        default:
425                if (currConsole == index)
426                {
427                        screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)]=c;
428                        screen[(cons->currY*(CONSOLE_WIDTH*2))+(cons->currX*2)+1]=cons->currColor;
429                }else{
430                        CONSOLE_BUF(index)[CONSOLE_IND(cons->currX*2, cons->currY)]=c;
431                        CONSOLE_BUF(index)[CONSOLE_IND(cons->currX*2, cons->currY)+1]=cons->currColor;
432                }
433               
434                cons->currX++;
435               
436                if (cons->currX >= CONSOLE_WIDTH)
437                        ConsoleNewLine(index);
438        }
439}
440
441void ConsoleWriteOutput(char* message, int length)
442{
443        ConsoleWriteString(currConsole, message, length);
444}
445
446static void ConsoleClearScreen(int index)
447{
448        if (consoles[index].flags & CONSOLE_GRAPHICS)
449                return;
450
451        int i;
452        if (currConsole == index)
453        {
454                for (i=0; i<(CONSOLE_WIDTH*CONSOLE_HEIGHT*2); i+=2)
455                {
456                        screen[i]=' ';
457                        screen[i+1]=7;
458                }
459        }else{
460                for (i=0; i<(CONSOLE_WIDTH*CONSOLE_HEIGHT*2); i+=2)
461                {
462                        scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+i]=' ';
463                        scrBuf[(CONSOLE_WIDTH*CONSOLE_HEIGHT*2*index)+i+1]=7;
464                }
465        }
466       
467        consoles[index].currX=0;
468        consoles[index].currY=0;
469       
470        ConsoleUpdateCursorPos(index);
471}
472
473void ConsoleClearCurrent()
474{
475        ConsoleClearScreen(currConsole);
476}
477
478static void ConsoleUpdateCursorPos(int console)
479{
480        WORD position;
481        struct Console* cons=&consoles[currConsole];
482
483        if (console != currConsole)
484                return;
485
486        position=(cons->currY*(CONSOLE_WIDTH))+cons->currX;
487
488        PreemptDisable();
489        outb(0x3D4,14);
490        outb(0x3D5,(BYTE)(position >> 8));
491        outb(0x3D4,15);
492        outb(0x3D5,(BYTE)(position & 0xFF));
493        PreemptFastEnable();
494}
495
496static void ConsoleGetCursorPos()
497{
498        DWORD flags;
499        WORD position;
500
501        IrqSaveFlags(flags);
502
503        outb(0x3D4, 14);
504        position=inb(0x3D5) << 8;
505        outb(0x3D4, 15);
506        position |= inb(0x3D5);
507
508        IrqRestoreFlags(flags);
509
510        consoles[currConsole].currX=position % 80;
511        consoles[currConsole].currY=position/80;
512}
513
514static void ConsoleNewLine(int index)
515{
516        struct Console* console=&consoles[index];
517       
518        console->currX=0;
519        console->currY++;
520       
521        if (console->currY == CONSOLE_HEIGHT)
522        {
523                console->currY=CONSOLE_HEIGHT-1;
524                ConsoleScrollScreen(index);
525        }
526       
527        ConsoleUpdateCursorPos(index);
528}
529
530static void ConsoleAddToQueue(BYTE n)
531{
532        BYTE head;
533        DWORD flags;
534        struct Console* currCons;
535
536        /* May not press keys before console array has been set up */
537        if (!scrBuf)
538                return;
539
540        currCons=&consoles[currConsole];
541
542        if (!currCons)
543                return;
544
545        IrqSaveFlags(flags);
546
547        head=(currCons->head+1) % CONSOLE_KEYBUF_SIZE;
548       
549//      KePrint("ConsoleAddToQueue(%u), %u %u\n", n, head, currCons->tail);
550       
551        if (head != currCons->tail)
552        {
553                currCons->keyboardBuf[currCons->head]=n;
554                currCons->head=head;
555                WakeUp(&currCons->waitQueue);
556        }else
557                KePrint("ConsoleAddToQueue: Keyboard buffer full!\n");
558
559        IrqRestoreFlags(flags);
560}
561
562void ConsoleAddKey(BYTE key)
563{
564        if (!(consoles[currConsole].flags & CONSOLE_SENDKEYC))
565                ConsoleAddToQueue(key);
566}
567
568SYMBOL_EXPORT(ConsoleAddKey);
569
570void ConsoleAddKeyCode(BYTE key)
571{       
572        if (consoles[currConsole].flags & CONSOLE_SENDKEYC)
573                ConsoleAddToQueue(key);
574}
575
576SYMBOL_EXPORT(ConsoleAddKeyCode);
577
578int ConsoleEarlyInit()
579{
580        ConsoleClearScreen(0);
581        consoles[0].currColor=7;
582        consoles[0].backColor=0;
583        return 0;
584}
585
586BYTE ConsoleGetCharacter()
587{
588        BYTE retVal=0;
589        struct Console* currCons=&consoles[currConsole];
590
591        if (currCons->head != currCons->tail)
592        {
593                retVal=currCons->keyboardBuf[currCons->tail] & 0xFF;
594                currCons->tail=(currCons->tail+1) % CONSOLE_KEYBUF_SIZE; /* Wraps around */
595                if (!(currCons->flags & CONSOLE_NO_ECHO) && retVal < 0x80 && current && retVal != '\b') DoWriteFile(current->files[0],&retVal,1);
596        }
597
598        return retVal;
599}
600
601int ConsoleDevRead(struct File* file,BYTE* data,DWORD size)
602{
603        int index=DEV_ID_MINOR(file->vNode->devId); /* TODO: Change. */
604        struct Console* currCons=&consoles[index];
605        DWORD i=0;
606        DWORD flags;
607
608        IrqSaveFlags(flags);
609
610        do
611        {
612                WAIT_ON(&consoles[index].waitQueue, currCons->head != currCons->tail);
613                data[i++]=ConsoleGetCharacter();
614        }while (i < size);
615
616        IrqRestoreFlags(flags);
617
618        return size;
619}
620
621int ConsoleDevWrite(struct File* file,BYTE* data,DWORD size)
622{               
623        return ConsoleWriteString(DEV_ID_MINOR(file->vNode->devId),(char*)data,size);
624}
625
626int ConsolePoll(struct File* file, struct PollItem* item, struct PollQueue* pollQueue)
627{
628        struct Console* cons=&consoles[DEV_ID_MINOR(file->vNode->devId)];
629
630        if ((item->events & POLL_IN) && cons->head != cons->tail)
631                item->revents |= POLL_IN;
632
633        /* The console can always be written to. */
634        if (item->events & POLL_OUT)
635                item->revents |= POLL_OUT;
636
637        PollAddWait(pollQueue, &cons->waitQueue);
638
639        return 0;
640}
641
642struct FileOps consoleOps={
643        .read = ConsoleDevRead, /* Read the keyboard buffer */
644        .write = ConsoleDevWrite,
645        .poll = ConsolePoll,
646};
647
648/* ConsoleGetCurrent also works for virtual terminals */
649
650int ConsoleGetCurrent(struct KeFsEntry** dest, struct KeFsEntry* src)
651{
652        struct VNode* vNode = current->files[0]->vNode;
653        struct KeFsEntry* entry = (struct KeFsEntry*)vNode->id;
654        struct KeObject* object = (struct KeObject*)entry->file;
655       
656        *dest = object->dir;
657               
658        if (!*dest)
659                return -ENOENT;
660       
661        return 0;
662}
663
664struct IcAttribute consAttributes[]=
665{
666        IC_END(),
667};
668
669KE_OBJECT_TYPE(consType, NULL);
670
671struct DevClass consoleClass;
672
673SYMBOL_EXPORT(consoleClass);
674
675static void ConsoleAddTextCons()
676{
677        int i;
678       
679        DevClassCreate(&consoleClass, &consType, "Consoles");
680
681        /* Register all the consoles */
682        for (i=0; i<MAX_CONSOLES; i++)
683        {
684                struct Console* curr=&consoles[i];
685               
686                KeDeviceCreate(&curr->device, &consoleClass.set, DEV_ID_MAKE(CONSOLE_MAJOR, i), &consoleOps, DEVICE_CHAR, "Console%d", i);
687               
688                INIT_LIST_HEAD(&curr->waitQueue.list);
689                consoles[i].currColor=7;
690                consoles[i].backColor=0;
691                consoles[i].currX=consoles[i].currY=0;
692                consoles[i].head=consoles[i].tail=0;
693       
694                /* Register each console's configuration options. TODO: Change to ICFS attributes. */
695                struct KeFsEntry* dir=KeDeviceGetConfDir(&curr->device);
696                               
697                IcFsAddIntEntry(dir, "flags", &curr->flags, VFS_ATTR_RW);
698                IcFsAddIntEntry(dir, "rows", &rows, VFS_ATTR_READ);
699                IcFsAddIntEntry(dir, "cols", &cols, VFS_ATTR_READ);
700                IcFsAddIntEntry(dir, "cursorRow", &curr->currY, VFS_ATTR_RW);
701                IcFsAddIntEntry(dir, "cursorCol", &curr->currX, VFS_ATTR_RW);
702        }
703       
704        /* Add a symbolic link for the current console used by the process. */
705        IcFsAddSoftLink(DevClassGetDir(&consoleClass), "currConsole", ConsoleGetCurrent);
706       
707        /* And the total number of text consoles. */
708        IcFsAddIntEntry(DevClassGetDir(&consoleClass), "numTextConsoles", &numTextConsoles, VFS_ATTR_READ);
709}
710
711int ConsoleInit()
712{
713        /* Now allocate all the other consoles, since dynamic memory allocation can be performed. */
714        scrBuf=(BYTE*)MemAlloc(MAX_CONSOLES*(CONSOLE_WIDTH*CONSOLE_HEIGHT*2));
715        if (!scrBuf)
716        {
717                KernelPanic("Failed to allocate memory for multiple consoles");
718                return -ENOMEM; /* Never reached. */
719        }
720
721        ZeroMemory(scrBuf,(MAX_CONSOLES*(CONSOLE_WIDTH*CONSOLE_HEIGHT*2)));
722       
723        ConsoleAddTextCons();
724
725        /* Get the current cursor position, and take over from the early console driver. */
726        ConsoleGetCursorPos();
727
728        KeSetOutput(ConsoleWriteOutput);
729       
730        KePrint("CONS: Registered %u text consoles.\n", MAX_CONSOLES);
731       
732        return 0;
733}
734
735ModuleInit(ConsoleInit);
Note: See TracBrowser for help on using the browser.