Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/char/briq_panel.c
15109 views
1
/*
2
* Drivers for the Total Impact PPC based computer "BRIQ"
3
* by Dr. Karsten Jeppesen
4
*
5
*/
6
7
#include <linux/module.h>
8
9
#include <linux/types.h>
10
#include <linux/errno.h>
11
#include <linux/tty.h>
12
#include <linux/timer.h>
13
#include <linux/kernel.h>
14
#include <linux/wait.h>
15
#include <linux/string.h>
16
#include <linux/ioport.h>
17
#include <linux/delay.h>
18
#include <linux/miscdevice.h>
19
#include <linux/fs.h>
20
#include <linux/mm.h>
21
#include <linux/init.h>
22
23
#include <asm/uaccess.h>
24
#include <asm/io.h>
25
#include <asm/prom.h>
26
27
#define BRIQ_PANEL_MINOR 156
28
#define BRIQ_PANEL_VFD_IOPORT 0x0390
29
#define BRIQ_PANEL_LED_IOPORT 0x0398
30
#define BRIQ_PANEL_VER "1.1 (04/20/2002)"
31
#define BRIQ_PANEL_MSG0 "Loading Linux"
32
33
static int vfd_is_open;
34
static unsigned char vfd[40];
35
static int vfd_cursor;
36
static unsigned char ledpb, led;
37
38
static void update_vfd(void)
39
{
40
int i;
41
42
/* cursor home */
43
outb(0x02, BRIQ_PANEL_VFD_IOPORT);
44
for (i=0; i<20; i++)
45
outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1);
46
47
/* cursor to next line */
48
outb(0xc0, BRIQ_PANEL_VFD_IOPORT);
49
for (i=20; i<40; i++)
50
outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1);
51
52
}
53
54
static void set_led(char state)
55
{
56
if (state == 'R')
57
led = 0x01;
58
else if (state == 'G')
59
led = 0x02;
60
else if (state == 'Y')
61
led = 0x03;
62
else if (state == 'X')
63
led = 0x00;
64
outb(led, BRIQ_PANEL_LED_IOPORT);
65
}
66
67
static int briq_panel_open(struct inode *ino, struct file *filep)
68
{
69
tty_lock();
70
/* enforce single access, vfd_is_open is protected by BKL */
71
if (vfd_is_open) {
72
tty_unlock();
73
return -EBUSY;
74
}
75
vfd_is_open = 1;
76
77
tty_unlock();
78
return 0;
79
}
80
81
static int briq_panel_release(struct inode *ino, struct file *filep)
82
{
83
if (!vfd_is_open)
84
return -ENODEV;
85
86
vfd_is_open = 0;
87
88
return 0;
89
}
90
91
static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count,
92
loff_t *ppos)
93
{
94
unsigned short c;
95
unsigned char cp;
96
97
if (!vfd_is_open)
98
return -ENODEV;
99
100
c = (inb(BRIQ_PANEL_LED_IOPORT) & 0x000c) | (ledpb & 0x0003);
101
set_led(' ');
102
/* upper button released */
103
if ((!(ledpb & 0x0004)) && (c & 0x0004)) {
104
cp = ' ';
105
ledpb = c;
106
if (copy_to_user(buf, &cp, 1))
107
return -EFAULT;
108
return 1;
109
}
110
/* lower button released */
111
else if ((!(ledpb & 0x0008)) && (c & 0x0008)) {
112
cp = '\r';
113
ledpb = c;
114
if (copy_to_user(buf, &cp, 1))
115
return -EFAULT;
116
return 1;
117
} else {
118
ledpb = c;
119
return 0;
120
}
121
}
122
123
static void scroll_vfd( void )
124
{
125
int i;
126
127
for (i=0; i<20; i++) {
128
vfd[i] = vfd[i+20];
129
vfd[i+20] = ' ';
130
}
131
vfd_cursor = 20;
132
}
133
134
static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len,
135
loff_t *ppos)
136
{
137
size_t indx = len;
138
int i, esc = 0;
139
140
if (!vfd_is_open)
141
return -EBUSY;
142
143
for (;;) {
144
char c;
145
if (!indx)
146
break;
147
if (get_user(c, buf))
148
return -EFAULT;
149
if (esc) {
150
set_led(c);
151
esc = 0;
152
} else if (c == 27) {
153
esc = 1;
154
} else if (c == 12) {
155
/* do a form feed */
156
for (i=0; i<40; i++)
157
vfd[i] = ' ';
158
vfd_cursor = 0;
159
} else if (c == 10) {
160
if (vfd_cursor < 20)
161
vfd_cursor = 20;
162
else if (vfd_cursor < 40)
163
vfd_cursor = 40;
164
else if (vfd_cursor < 60)
165
vfd_cursor = 60;
166
if (vfd_cursor > 59)
167
scroll_vfd();
168
} else {
169
/* just a character */
170
if (vfd_cursor > 39)
171
scroll_vfd();
172
vfd[vfd_cursor++] = c;
173
}
174
indx--;
175
buf++;
176
}
177
update_vfd();
178
179
return len;
180
}
181
182
static const struct file_operations briq_panel_fops = {
183
.owner = THIS_MODULE,
184
.read = briq_panel_read,
185
.write = briq_panel_write,
186
.open = briq_panel_open,
187
.release = briq_panel_release,
188
.llseek = noop_llseek,
189
};
190
191
static struct miscdevice briq_panel_miscdev = {
192
BRIQ_PANEL_MINOR,
193
"briq_panel",
194
&briq_panel_fops
195
};
196
197
static int __init briq_panel_init(void)
198
{
199
struct device_node *root = of_find_node_by_path("/");
200
const char *machine;
201
int i;
202
203
machine = of_get_property(root, "model", NULL);
204
if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) {
205
of_node_put(root);
206
return -ENODEV;
207
}
208
of_node_put(root);
209
210
printk(KERN_INFO
211
"briq_panel: v%s Dr. Karsten Jeppesen ([email protected])\n",
212
BRIQ_PANEL_VER);
213
214
if (!request_region(BRIQ_PANEL_VFD_IOPORT, 4, "BRIQ Front Panel"))
215
return -EBUSY;
216
217
if (!request_region(BRIQ_PANEL_LED_IOPORT, 2, "BRIQ Front Panel")) {
218
release_region(BRIQ_PANEL_VFD_IOPORT, 4);
219
return -EBUSY;
220
}
221
ledpb = inb(BRIQ_PANEL_LED_IOPORT) & 0x000c;
222
223
if (misc_register(&briq_panel_miscdev) < 0) {
224
release_region(BRIQ_PANEL_VFD_IOPORT, 4);
225
release_region(BRIQ_PANEL_LED_IOPORT, 2);
226
return -EBUSY;
227
}
228
229
outb(0x38, BRIQ_PANEL_VFD_IOPORT); /* Function set */
230
outb(0x01, BRIQ_PANEL_VFD_IOPORT); /* Clear display */
231
outb(0x0c, BRIQ_PANEL_VFD_IOPORT); /* Display on */
232
outb(0x06, BRIQ_PANEL_VFD_IOPORT); /* Entry normal */
233
for (i=0; i<40; i++)
234
vfd[i]=' ';
235
#ifndef MODULE
236
vfd[0] = 'L';
237
vfd[1] = 'o';
238
vfd[2] = 'a';
239
vfd[3] = 'd';
240
vfd[4] = 'i';
241
vfd[5] = 'n';
242
vfd[6] = 'g';
243
vfd[7] = ' ';
244
vfd[8] = '.';
245
vfd[9] = '.';
246
vfd[10] = '.';
247
#endif /* !MODULE */
248
249
update_vfd();
250
251
return 0;
252
}
253
254
static void __exit briq_panel_exit(void)
255
{
256
misc_deregister(&briq_panel_miscdev);
257
release_region(BRIQ_PANEL_VFD_IOPORT, 4);
258
release_region(BRIQ_PANEL_LED_IOPORT, 2);
259
}
260
261
module_init(briq_panel_init);
262
module_exit(briq_panel_exit);
263
264
MODULE_LICENSE("GPL");
265
MODULE_AUTHOR("Karsten Jeppesen <[email protected]>");
266
MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel");
267
268