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

Revision 403, 5.2 kB (checked in by mwhitworth, 4 months ago)

DOS to UNIX line endings.

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