root / Whitix / branches / scheduler / video / virtual.c

Revision 706, 5.4 kB (checked in by mwhitworth, 6 months ago)

Add CONSOLE_GET_POS ioctl.

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/* TODO: Needs to be tightened up and rewritten in parts. sprintf'ing on user buffers
20 * is not a good idea. */
21
22#include <console.h>
23#include <fs/devfs.h>
24#include <fs/vfs.h>
25#include <init.h>
26#include <error.h>
27#include <malloc.h>
28#include <i386/ioports.h>
29#include <task.h>
30#include <net/network.h>
31#include <net/socket.h>
32
33#define VIRTUAL_MAX             10
34#define VIRTUAL_BUFFER_SIZE             4096
35
36/* Device number */
37#define VIRTUAL_MAJOR   255
38
39/* Master ioctls */
40#define VIRTUAL_OPEN_MASTER             0
41
42/* Master child ioctls */
43#define VIRTUAL_GET_NAME                0
44
45struct VirtualTerm
46{
47        struct File* master;
48        char* masterOutput;
49        int masterHead, masterTail;
50        WaitQueue masterQueue;
51        char* slavesOutput;
52        int slaveHead, slaveTail;
53        WaitQueue slaveQueue;
54};
55
56struct FileOps vChildOps;
57
58struct VirtualTerm virtualT[VIRTUAL_MAX];
59
60struct VirtualTerm* VirtualTermGet(struct File* file)
61{
62        return &virtualT[file->vNode->devId.minor-1];
63}
64
65int VirtualChildRead(struct File* file, char* data, unsigned int length)
66{
67        struct VirtualTerm* vTerm;
68        DWORD size=0, oldSize;
69        DWORD flags;
70
71        vTerm=VirtualTermGet(file);
72
73        if (file == vTerm->master)
74        {
75                WAIT_ON(vTerm->slaveQueue, vTerm->slaveHead != vTerm->slaveTail);
76
77                IrqSaveFlags(flags);
78                size=MIN(vTerm->slaveHead-vTerm->slaveTail, length);
79                oldSize=size;
80
81                while (size--)
82                {
83                        *data++=vTerm->slavesOutput[vTerm->slaveTail++];
84                        vTerm->slaveTail &= VIRTUAL_BUFFER_SIZE-1;
85                }
86        }else{
87                WAIT_ON(vTerm->masterQueue, vTerm->masterHead != vTerm->masterTail);
88
89                IrqSaveFlags(flags);
90                size=MIN(vTerm->masterHead-vTerm->masterTail, length);
91                oldSize=size;
92
93                while (size--)
94                {
95                        *data++=vTerm->masterOutput[vTerm->masterTail++];
96                        vTerm->masterTail &= VIRTUAL_BUFFER_SIZE-1;
97                }
98        }
99
100        IrqRestoreFlags(flags);
101
102        return oldSize;
103}
104
105int VirtualChildWrite(struct File* file, char* data, unsigned int length)
106{
107        struct VirtualTerm* vTerm;
108        DWORD flags;
109        unsigned int tempLength;
110        vTerm=VirtualTermGet(file);
111
112        IrqSaveFlags(flags);
113        tempLength=length;
114
115        if (file == vTerm->master)
116        {
117                /* Echo */
118                memcpy(&vTerm->masterOutput[vTerm->masterHead], data, length);
119                vTerm->masterHead+=length;
120
121                /* TODO: Add noecho option. See ConsoleIoCtl */
122                memcpy(&vTerm->slavesOutput[vTerm->slaveHead], data, length);
123                vTerm->slaveHead+=length;
124
125                WakeUp(&vTerm->masterQueue);
126        }else{
127                IrqSaveFlags(flags);
128//              length=MIN(vTerm->slaveHead-vTerm->Tail, length);
129
130                while (length--)
131                {
132                        vTerm->slavesOutput[vTerm->slaveHead++]=*data++;
133                        vTerm->slaveHead &= VIRTUAL_BUFFER_SIZE-1;
134                }
135
136                WakeUp(&vTerm->slaveQueue);
137        }
138
139        IrqRestoreFlags(flags);
140
141        return tempLength;
142}
143
144int VirtualChildIoCtl(struct File* file, unsigned long code, char* data)
145{
146        switch (code)
147        {
148                case VIRTUAL_GET_NAME:
149                        sprintf(data, "Consoles/Virtual%d", file->vNode->devId.minor-1);
150                        return 0;
151        }
152
153        return 0;
154}
155
156int VirtualChildPoll(struct File* file, struct PollItem* item, struct PollQueue* pollQueue)
157{
158        struct VirtualTerm* vTerm;
159
160        vTerm=VirtualTermGet(file);
161
162        if (file == vTerm->master)
163        {
164                if ((item->events & POLL_IN) && vTerm->slaveHead != vTerm->slaveTail)
165                        item->revents |= POLL_IN;
166
167                if ((item->events & POLL_OUT) && vTerm->masterTail != ((vTerm->masterHead - 1) % VIRTUAL_BUFFER_SIZE))
168                        item->revents |= POLL_OUT;
169
170                PollAddWait(pollQueue, &vTerm->slaveQueue);
171        }else{
172                KePrint("Slave poll\n");
173        }
174
175        return 0;
176}
177
178struct FileOps vChildOps=
179{
180        .read = VirtualChildRead,
181        .write = VirtualChildWrite,
182        .ioctl = VirtualChildIoCtl,
183        .poll = VirtualChildPoll,
184};
185
186int VirtualOpenMaster(int* fd)
187{
188        char buf[32];
189        char path[64];
190        int i=0;
191
192        for (i=0; i<VIRTUAL_MAX; i++)
193                if (!virtualT[i].master)
194                        break;
195
196        if (i == VIRTUAL_MAX)
197                return -EMFILE;
198
199        sprintf(buf, "Consoles/Virtual%d", i);
200
201        DevAddDevice(buf, VIRTUAL_MAJOR, i+1, DEVICE_CHAR, &vChildOps);
202
203        *fd=VfsGetFreeFd(current);
204
205        if (*fd < 0)
206                return *fd;
207
208        sprintf(path, "%s/%s", DEVICES_PATH, buf);
209
210        virtualT[i].master = &current->files[*fd];
211
212        /* Allocate buffers for I/O, before anything happens. */
213        virtualT[i].masterOutput=(char*)malloc(VIRTUAL_BUFFER_SIZE);
214        virtualT[i].slavesOutput=(char*)malloc(VIRTUAL_BUFFER_SIZE);
215
216        INIT_WAITQUEUE_HEAD(&virtualT[i].masterQueue);
217        INIT_WAITQUEUE_HEAD(&virtualT[i].slaveQueue);
218
219        /* TODO: Handle case where DoOpenFile is not successful. */
220
221        return DoOpenFile(&current->files[*fd], path, 0, 0);
222}
223
224int VirtualMasterIoCtl(struct File* file, unsigned long code, char* data)
225{
226        switch (code)
227        {
228                case VIRTUAL_OPEN_MASTER:
229                        return VirtualOpenMaster((int*)data);
230        }
231
232        return -ENOTIMPL;
233}
234
235struct FileOps vMasterOps=
236{
237        .ioctl = VirtualMasterIoCtl,
238};
239
240int VirtualInit()
241{
242        ZeroMemory(virtualT, VIRTUAL_MAX * sizeof(struct VirtualTerm));
243
244        DevAddDevice("Consoles/VirtualMaster", VIRTUAL_MAJOR, 0, DEVICE_CHAR, &vMasterOps);
245        return 0;
246}
247
248DeviceInit(VirtualInit);
Note: See TracBrowser for help on using the browser.