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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [vc_screen.c] - Blame information for rev 1626

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * linux/drivers/char/vc_screen.c
3
 *
4
 * Provide access to virtual console memory.
5
 * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
6
 * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
7
 *            [minor: N]
8
 *
9
 * /dev/vcsaN: idem, but including attributes, and prefixed with
10
 *      the 4 bytes lines,columns,x,y (as screendump used to give)
11
 *            [minor: N+128]
12
 *
13
 * This replaces screendump and part of selection, so that the system
14
 * administrator can control access using file system permissions.
15
 *
16
 * aeb@cwi.nl - efter Friedas begravelse - 950211
17
 */
18
 
19
#include <linux/kernel.h>
20
#include <linux/major.h>
21
#include <linux/errno.h>
22
#include <linux/tty.h>
23
#include <linux/fs.h>
24
#include <asm/segment.h>
25
#include "vt_kern.h"
26
#include "selection.h"
27
 
28
#define HEADER_SIZE     4
29
 
30
static inline int
31
vcs_size(struct inode *inode)
32
{
33
        int size = video_num_lines * video_num_columns;
34
        if (MINOR(inode->i_rdev) & 128)
35
                size = 2*size + HEADER_SIZE;
36
        return size;
37
}
38
 
39
static int
40
vcs_lseek(struct inode *inode, struct file *file, off_t offset, int orig)
41
{
42
        int size = vcs_size(inode);
43
 
44
        switch (orig) {
45
                case 0:
46
                        file->f_pos = offset;
47
                        break;
48
                case 1:
49
                        file->f_pos += offset;
50
                        break;
51
                case 2:
52
                        file->f_pos = size + offset;
53
                        break;
54
                default:
55
                        return -EINVAL;
56
        }
57
        if (file->f_pos < 0 || file->f_pos > size)
58
                return -EINVAL;
59
        return file->f_pos;
60
}
61
 
62
static int
63
vcs_read(struct inode *inode, struct file *file, char *buf, int count)
64
{
65
        unsigned long p = file->f_pos;
66
        unsigned int cons = MINOR(inode->i_rdev);
67
        int viewed, attr, size, read;
68
        char *buf0;
69
        unsigned short *org;
70
 
71
        attr = (cons & 128);
72
        cons = (cons & 127);
73
        if (cons == 0) {
74
                cons = fg_console;
75
                viewed = 1;
76
        } else {
77
                cons--;
78
                viewed = 0;
79
        }
80
        if (!vc_cons_allocated(cons))
81
                return -ENXIO;
82
 
83
        size = vcs_size(inode);
84
        if (count < 0 || p > size)
85
                return -EINVAL;
86
        if (count > size - p)
87
                count = size - p;
88
 
89
        buf0 = buf;
90
        if (!attr) {
91
                org = screen_pos(cons, p, viewed);
92
                while (count-- > 0)
93
                        put_user(scr_readw(org++) & 0xff, buf++);
94
        } else {
95
                if (p < HEADER_SIZE) {
96
                        char header[HEADER_SIZE];
97
                        header[0] = (char) video_num_lines;
98
                        header[1] = (char) video_num_columns;
99
                        getconsxy(cons, header+2);
100
                        while (p < HEADER_SIZE && count-- > 0)
101
                            put_user(header[p++], buf++);
102
                }
103
                p -= HEADER_SIZE;
104
                org = screen_pos(cons, p/2, viewed);
105
                if ((p & 1) && count-- > 0)
106
                        put_user(scr_readw(org++) >> 8, buf++);
107
                while (count > 1) {
108
                        put_user(scr_readw(org++), (unsigned short *) buf);
109
                        buf += 2;
110
                        count -= 2;
111
                }
112
                if (count > 0)
113
                        put_user(scr_readw(org) & 0xff, buf++);
114
        }
115
        read = buf - buf0;
116
        file->f_pos += read;
117
        return read;
118
}
119
 
120
static int
121
vcs_write(struct inode *inode, struct file *file, const char *buf, int count)
122
{
123
        unsigned long p = file->f_pos;
124
        unsigned int cons = MINOR(inode->i_rdev);
125
        int viewed, attr, size, written;
126
        const char *buf0;
127
        unsigned short *org;
128
 
129
        attr = (cons & 128);
130
        cons = (cons & 127);
131
        if (cons == 0) {
132
                cons = fg_console;
133
                viewed = 1;
134
        } else {
135
                cons--;
136
                viewed = 0;
137
        }
138
        if (!vc_cons_allocated(cons))
139
                return -ENXIO;
140
 
141
        size = vcs_size(inode);
142
        if (count < 0 || p > size)
143
                return -EINVAL;
144
        if (count > size - p)
145
                count = size - p;
146
 
147
        buf0 = buf;
148
        if (!attr) {
149
                org = screen_pos(cons, p, viewed);
150
                while (count-- > 0) {
151
                        scr_writew((scr_readw(org) & 0xff00) |
152
                                   get_user((const unsigned char*)buf++), org);
153
                        org++;
154
                }
155
        } else {
156
                if (p < HEADER_SIZE) {
157
                        char header[HEADER_SIZE];
158
                        getconsxy(cons, header+2);
159
                        while (p < HEADER_SIZE && count-- > 0)
160
                                header[p++] = get_user(buf++);
161
                        if (!viewed)
162
                                putconsxy(cons, header+2);
163
                }
164
                p -= HEADER_SIZE;
165
                org = screen_pos(cons, p/2, viewed);
166
                if ((p & 1) && count-- > 0) {
167
                        scr_writew((get_user(buf++) << 8) |
168
                                   (scr_readw(org) & 0xff), org);
169
                        org++;
170
                }
171
                while (count > 1) {
172
                        scr_writew(get_user((const unsigned short *) buf), org++);
173
                        buf += 2;
174
                        count -= 2;
175
                }
176
                if (count > 0)
177
                        scr_writew((scr_readw(org) & 0xff00) |
178
                                   get_user((const unsigned char*)buf++), org);
179
        }
180
        written = buf - buf0;
181
        file->f_pos += written;
182
        return written;
183
}
184
 
185
static int
186
vcs_open(struct inode *inode, struct file *filp)
187
{
188
        unsigned int cons = (MINOR(inode->i_rdev) & 127);
189
        if(cons && !vc_cons_allocated(cons-1))
190
                return -ENXIO;
191
        return 0;
192
}
193
 
194
static struct file_operations vcs_fops = {
195
        vcs_lseek,      /* lseek */
196
        vcs_read,       /* read */
197
        vcs_write,      /* write */
198
        NULL,           /* readdir */
199
        NULL,           /* select */
200
        NULL,           /* ioctl */
201
        NULL,           /* mmap */
202
        vcs_open,       /* open */
203
        NULL,           /* release */
204
        NULL            /* fsync */
205
};
206
 
207
int vcs_init(void)
208
{
209
        int error;
210
 
211
        error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops);
212
        if (error)
213
                printk("unable to get major %d for vcs device", VCS_MAJOR);
214
        return error;
215
}

powered by: WebSVN 2.1.0

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