aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/char
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/briq_panel.c266
-rw-r--r--drivers/char/dcc_tty.c326
-rw-r--r--drivers/char/ramoops.c250
-rw-r--r--drivers/char/scc.h613
-rw-r--r--drivers/char/tpm/tpm_bios.c556
-rw-r--r--drivers/char/viotape.c1041
6 files changed, 3052 insertions, 0 deletions
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
new file mode 100644
index 00000000000..095ab90535c
--- /dev/null
+++ b/drivers/char/briq_panel.c
@@ -0,0 +1,266 @@
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
33static int vfd_is_open;
34static unsigned char vfd[40];
35static int vfd_cursor;
36static unsigned char ledpb, led;
37
38static 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
54static 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
67static 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
81static 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
91static 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
123static 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
134static 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
182static 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
191static struct miscdevice briq_panel_miscdev = {
192 BRIQ_PANEL_MINOR,
193 "briq_panel",
194 &briq_panel_fops
195};
196
197static 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 (kj@totalimpact.com)\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
254static 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
261module_init(briq_panel_init);
262module_exit(briq_panel_exit);
263
264MODULE_LICENSE("GPL");
265MODULE_AUTHOR("Karsten Jeppesen <karsten@jeppesens.com>");
266MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel");
diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c
new file mode 100644
index 00000000000..a787accdcb1
--- /dev/null
+++ b/drivers/char/dcc_tty.c
@@ -0,0 +1,326 @@
1/* drivers/char/dcc_tty.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/delay.h>
19#include <linux/console.h>
20#include <linux/hrtimer.h>
21#include <linux/tty.h>
22#include <linux/tty_driver.h>
23#include <linux/tty_flip.h>
24
25MODULE_DESCRIPTION("DCC TTY Driver");
26MODULE_LICENSE("GPL");
27MODULE_VERSION("1.0");
28
29static spinlock_t g_dcc_tty_lock = SPIN_LOCK_UNLOCKED;
30static struct hrtimer g_dcc_timer;
31static char g_dcc_buffer[16];
32static int g_dcc_buffer_head;
33static int g_dcc_buffer_count;
34static unsigned g_dcc_write_delay_usecs = 1;
35static struct tty_driver *g_dcc_tty_driver;
36static struct tty_struct *g_dcc_tty;
37static int g_dcc_tty_open_count;
38
39static void dcc_poll_locked(void)
40{
41 char ch;
42 int rch;
43 int written;
44
45 while (g_dcc_buffer_count) {
46 ch = g_dcc_buffer[g_dcc_buffer_head];
47 asm(
48 "mrc 14, 0, r15, c0, c1, 0\n"
49 "mcrcc 14, 0, %1, c0, c5, 0\n"
50 "movcc %0, #1\n"
51 "movcs %0, #0\n"
52 : "=r" (written)
53 : "r" (ch)
54 );
55 if (written) {
56 if (ch == '\n')
57 g_dcc_buffer[g_dcc_buffer_head] = '\r';
58 else {
59 g_dcc_buffer_head = (g_dcc_buffer_head + 1) % ARRAY_SIZE(g_dcc_buffer);
60 g_dcc_buffer_count--;
61 if (g_dcc_tty)
62 tty_wakeup(g_dcc_tty);
63 }
64 g_dcc_write_delay_usecs = 1;
65 } else {
66 if (g_dcc_write_delay_usecs > 0x100)
67 break;
68 g_dcc_write_delay_usecs <<= 1;
69 udelay(g_dcc_write_delay_usecs);
70 }
71 }
72
73 if (g_dcc_tty && !test_bit(TTY_THROTTLED, &g_dcc_tty->flags)) {
74 asm(
75 "mrc 14, 0, %0, c0, c1, 0\n"
76 "tst %0, #(1 << 30)\n"
77 "moveq %0, #-1\n"
78 "mrcne 14, 0, %0, c0, c5, 0\n"
79 : "=r" (rch)
80 );
81 if (rch >= 0) {
82 ch = rch;
83 tty_insert_flip_string(g_dcc_tty, &ch, 1);
84 tty_flip_buffer_push(g_dcc_tty);
85 }
86 }
87
88
89 if (g_dcc_buffer_count)
90 hrtimer_start(&g_dcc_timer, ktime_set(0, g_dcc_write_delay_usecs * NSEC_PER_USEC), HRTIMER_MODE_REL);
91 else
92 hrtimer_start(&g_dcc_timer, ktime_set(0, 20 * NSEC_PER_MSEC), HRTIMER_MODE_REL);
93}
94
95static int dcc_tty_open(struct tty_struct * tty, struct file * filp)
96{
97 int ret;
98 unsigned long irq_flags;
99
100 spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
101 if (g_dcc_tty == NULL || g_dcc_tty == tty) {
102 g_dcc_tty = tty;
103 g_dcc_tty_open_count++;
104 ret = 0;
105 } else
106 ret = -EBUSY;
107 spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
108
109 printk("dcc_tty_open, tty %p, f_flags %x, returned %d\n", tty, filp->f_flags, ret);
110
111 return ret;
112}
113
114static void dcc_tty_close(struct tty_struct * tty, struct file * filp)
115{
116 printk("dcc_tty_close, tty %p, f_flags %x\n", tty, filp->f_flags);
117 if (g_dcc_tty == tty) {
118 if (--g_dcc_tty_open_count == 0)
119 g_dcc_tty = NULL;
120 }
121}
122
123static int dcc_write(const unsigned char *buf_start, int count)
124{
125 const unsigned char *buf = buf_start;
126 unsigned long irq_flags;
127 int copy_len;
128 int space_left;
129 int tail;
130
131 if (count < 1)
132 return 0;
133
134 spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
135 do {
136 tail = (g_dcc_buffer_head + g_dcc_buffer_count) % ARRAY_SIZE(g_dcc_buffer);
137 copy_len = ARRAY_SIZE(g_dcc_buffer) - tail;
138 space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
139 if (copy_len > space_left)
140 copy_len = space_left;
141 if (copy_len > count)
142 copy_len = count;
143 memcpy(&g_dcc_buffer[tail], buf, copy_len);
144 g_dcc_buffer_count += copy_len;
145 buf += copy_len;
146 count -= copy_len;
147 if (copy_len < count && copy_len < space_left) {
148 space_left -= copy_len;
149 copy_len = count;
150 if (copy_len > space_left) {
151 copy_len = space_left;
152 }
153 memcpy(g_dcc_buffer, buf, copy_len);
154 buf += copy_len;
155 count -= copy_len;
156 g_dcc_buffer_count += copy_len;
157 }
158 dcc_poll_locked();
159 space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
160 } while(count && space_left);
161 spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
162 return buf - buf_start;
163}
164
165static int dcc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count)
166{
167 int ret;
168 /* printk("dcc_tty_write %p, %d\n", buf, count); */
169 ret = dcc_write(buf, count);
170 if (ret != count)
171 printk("dcc_tty_write %p, %d, returned %d\n", buf, count, ret);
172 return ret;
173}
174
175static int dcc_tty_write_room(struct tty_struct *tty)
176{
177 int space_left;
178 unsigned long irq_flags;
179
180 spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
181 space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
182 spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
183 return space_left;
184}
185
186static int dcc_tty_chars_in_buffer(struct tty_struct *tty)
187{
188 int ret;
189 asm(
190 "mrc 14, 0, %0, c0, c1, 0\n"
191 "mov %0, %0, LSR #30\n"
192 "and %0, %0, #1\n"
193 : "=r" (ret)
194 );
195 return ret;
196}
197
198static void dcc_tty_unthrottle(struct tty_struct * tty)
199{
200 unsigned long irq_flags;
201
202 spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
203 dcc_poll_locked();
204 spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
205}
206
207static enum hrtimer_restart dcc_tty_timer_func(struct hrtimer *timer)
208{
209 unsigned long irq_flags;
210
211 spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
212 dcc_poll_locked();
213 spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
214 return HRTIMER_NORESTART;
215}
216
217void dcc_console_write(struct console *co, const char *b, unsigned count)
218{
219#if 1
220 dcc_write(b, count);
221#else
222 /* blocking printk */
223 while (count > 0) {
224 int written;
225 written = dcc_write(b, count);
226 if (written) {
227 b += written;
228 count -= written;
229 }
230 }
231#endif
232}
233
234static struct tty_driver *dcc_console_device(struct console *c, int *index)
235{
236 *index = 0;
237 return g_dcc_tty_driver;
238}
239
240static int __init dcc_console_setup(struct console *co, char *options)
241{
242 if (co->index != 0)
243 return -ENODEV;
244 return 0;
245}
246
247
248static struct console dcc_console =
249{
250 .name = "ttyDCC",
251 .write = dcc_console_write,
252 .device = dcc_console_device,
253 .setup = dcc_console_setup,
254 .flags = CON_PRINTBUFFER,
255 .index = -1,
256};
257
258static struct tty_operations dcc_tty_ops = {
259 .open = dcc_tty_open,
260 .close = dcc_tty_close,
261 .write = dcc_tty_write,
262 .write_room = dcc_tty_write_room,
263 .chars_in_buffer = dcc_tty_chars_in_buffer,
264 .unthrottle = dcc_tty_unthrottle,
265};
266
267static int __init dcc_tty_init(void)
268{
269 int ret;
270
271 hrtimer_init(&g_dcc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
272 g_dcc_timer.function = dcc_tty_timer_func;
273
274 g_dcc_tty_driver = alloc_tty_driver(1);
275 if (!g_dcc_tty_driver) {
276 printk(KERN_ERR "dcc_tty_probe: alloc_tty_driver failed\n");
277 ret = -ENOMEM;
278 goto err_alloc_tty_driver_failed;
279 }
280 g_dcc_tty_driver->owner = THIS_MODULE;
281 g_dcc_tty_driver->driver_name = "dcc";
282 g_dcc_tty_driver->name = "ttyDCC";
283 g_dcc_tty_driver->major = 0; // auto assign
284 g_dcc_tty_driver->minor_start = 0;
285 g_dcc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
286 g_dcc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
287 g_dcc_tty_driver->init_termios = tty_std_termios;
288 g_dcc_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
289 tty_set_operations(g_dcc_tty_driver, &dcc_tty_ops);
290 ret = tty_register_driver(g_dcc_tty_driver);
291 if (ret) {
292 printk(KERN_ERR "dcc_tty_probe: tty_register_driver failed, %d\n", ret);
293 goto err_tty_register_driver_failed;
294 }
295 tty_register_device(g_dcc_tty_driver, 0, NULL);
296
297 register_console(&dcc_console);
298 hrtimer_start(&g_dcc_timer, ktime_set(0, 0), HRTIMER_MODE_REL);
299
300 return 0;
301
302err_tty_register_driver_failed:
303 put_tty_driver(g_dcc_tty_driver);
304 g_dcc_tty_driver = NULL;
305err_alloc_tty_driver_failed:
306 return ret;
307}
308
309static void __exit dcc_tty_exit(void)
310{
311 int ret;
312
313 tty_unregister_device(g_dcc_tty_driver, 0);
314 ret = tty_unregister_driver(g_dcc_tty_driver);
315 if (ret < 0) {
316 printk(KERN_ERR "dcc_tty_remove: tty_unregister_driver failed, %d\n", ret);
317 } else {
318 put_tty_driver(g_dcc_tty_driver);
319 }
320 g_dcc_tty_driver = NULL;
321}
322
323module_init(dcc_tty_init);
324module_exit(dcc_tty_exit);
325
326
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
new file mode 100644
index 00000000000..810aff9e750
--- /dev/null
+++ b/drivers/char/ramoops.c
@@ -0,0 +1,250 @@
1/*
2 * RAM Oops/Panic logger
3 *
4 * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include <linux/kernel.h>
25#include <linux/err.h>
26#include <linux/module.h>
27#include <linux/kmsg_dump.h>
28#include <linux/time.h>
29#include <linux/io.h>
30#include <linux/ioport.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33#include <linux/ramoops.h>
34
35#define RAMOOPS_KERNMSG_HDR "===="
36#define MIN_MEM_SIZE 4096UL
37
38static ulong record_size = MIN_MEM_SIZE;
39module_param(record_size, ulong, 0400);
40MODULE_PARM_DESC(record_size,
41 "size of each dump done on oops/panic");
42
43static ulong mem_address;
44module_param(mem_address, ulong, 0400);
45MODULE_PARM_DESC(mem_address,
46 "start of reserved RAM used to store oops/panic logs");
47
48static ulong mem_size;
49module_param(mem_size, ulong, 0400);
50MODULE_PARM_DESC(mem_size,
51 "size of reserved RAM used to store oops/panic logs");
52
53static int dump_oops = 1;
54module_param(dump_oops, int, 0600);
55MODULE_PARM_DESC(dump_oops,
56 "set to 1 to dump oopses, 0 to only dump panics (default 1)");
57
58static struct ramoops_context {
59 struct kmsg_dumper dump;
60 void *virt_addr;
61 phys_addr_t phys_addr;
62 unsigned long size;
63 unsigned long record_size;
64 int dump_oops;
65 int count;
66 int max_count;
67} oops_cxt;
68
69static struct platform_device *dummy;
70static struct ramoops_platform_data *dummy_data;
71
72static void ramoops_do_dump(struct kmsg_dumper *dumper,
73 enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
74 const char *s2, unsigned long l2)
75{
76 struct ramoops_context *cxt = container_of(dumper,
77 struct ramoops_context, dump);
78 unsigned long s1_start, s2_start;
79 unsigned long l1_cpy, l2_cpy;
80 int res, hdr_size;
81 char *buf, *buf_orig;
82 struct timeval timestamp;
83
84 if (reason != KMSG_DUMP_OOPS &&
85 reason != KMSG_DUMP_PANIC &&
86 reason != KMSG_DUMP_KEXEC)
87 return;
88
89 /* Only dump oopses if dump_oops is set */
90 if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
91 return;
92
93 buf = cxt->virt_addr + (cxt->count * cxt->record_size);
94 buf_orig = buf;
95
96 memset(buf, '\0', cxt->record_size);
97 res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
98 buf += res;
99 do_gettimeofday(&timestamp);
100 res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
101 buf += res;
102
103 hdr_size = buf - buf_orig;
104 l2_cpy = min(l2, cxt->record_size - hdr_size);
105 l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
106
107 s2_start = l2 - l2_cpy;
108 s1_start = l1 - l1_cpy;
109
110 memcpy(buf, s1 + s1_start, l1_cpy);
111 memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
112
113 cxt->count = (cxt->count + 1) % cxt->max_count;
114}
115
116static int __init ramoops_probe(struct platform_device *pdev)
117{
118 struct ramoops_platform_data *pdata = pdev->dev.platform_data;
119 struct ramoops_context *cxt = &oops_cxt;
120 int err = -EINVAL;
121
122 if (!pdata->mem_size || !pdata->record_size) {
123 pr_err("The memory size and the record size must be "
124 "non-zero\n");
125 goto fail3;
126 }
127
128 rounddown_pow_of_two(pdata->mem_size);
129 rounddown_pow_of_two(pdata->record_size);
130
131 /* Check for the minimum memory size */
132 if (pdata->mem_size < MIN_MEM_SIZE &&
133 pdata->record_size < MIN_MEM_SIZE) {
134 pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
135 goto fail3;
136 }
137
138 if (pdata->mem_size < pdata->record_size) {
139 pr_err("The memory size must be larger than the "
140 "records size\n");
141 goto fail3;
142 }
143
144 cxt->max_count = pdata->mem_size / pdata->record_size;
145 cxt->count = 0;
146 cxt->size = pdata->mem_size;
147 cxt->phys_addr = pdata->mem_address;
148 cxt->record_size = pdata->record_size;
149 cxt->dump_oops = pdata->dump_oops;
150 /*
151 * Update the module parameter variables as well so they are visible
152 * through /sys/module/ramoops/parameters/
153 */
154 mem_size = pdata->mem_size;
155 mem_address = pdata->mem_address;
156 record_size = pdata->record_size;
157 dump_oops = pdata->dump_oops;
158
159 if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
160 pr_err("request mem region failed\n");
161 err = -EINVAL;
162 goto fail3;
163 }
164
165 cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
166 if (!cxt->virt_addr) {
167 pr_err("ioremap failed\n");
168 goto fail2;
169 }
170
171 cxt->dump.dump = ramoops_do_dump;
172 err = kmsg_dump_register(&cxt->dump);
173 if (err) {
174 pr_err("registering kmsg dumper failed\n");
175 goto fail1;
176 }
177
178 return 0;
179
180fail1:
181 iounmap(cxt->virt_addr);
182fail2:
183 release_mem_region(cxt->phys_addr, cxt->size);
184fail3:
185 return err;
186}
187
188static int __exit ramoops_remove(struct platform_device *pdev)
189{
190 struct ramoops_context *cxt = &oops_cxt;
191
192 if (kmsg_dump_unregister(&cxt->dump) < 0)
193 pr_warn("could not unregister kmsg_dumper\n");
194
195 iounmap(cxt->virt_addr);
196 release_mem_region(cxt->phys_addr, cxt->size);
197 return 0;
198}
199
200static struct platform_driver ramoops_driver = {
201 .remove = __exit_p(ramoops_remove),
202 .driver = {
203 .name = "ramoops",
204 .owner = THIS_MODULE,
205 },
206};
207
208static int __init ramoops_init(void)
209{
210 int ret;
211 ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
212 if (ret == -ENODEV) {
213 /*
214 * If we didn't find a platform device, we use module parameters
215 * building platform data on the fly.
216 */
217 pr_info("platform device not found, using module parameters\n");
218 dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
219 GFP_KERNEL);
220 if (!dummy_data)
221 return -ENOMEM;
222 dummy_data->mem_size = mem_size;
223 dummy_data->mem_address = mem_address;
224 dummy_data->record_size = record_size;
225 dummy_data->dump_oops = dump_oops;
226 dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
227 NULL, 0, dummy_data,
228 sizeof(struct ramoops_platform_data));
229
230 if (IS_ERR(dummy))
231 ret = PTR_ERR(dummy);
232 else
233 ret = 0;
234 }
235
236 return ret;
237}
238
239static void __exit ramoops_exit(void)
240{
241 platform_driver_unregister(&ramoops_driver);
242 kfree(dummy_data);
243}
244
245module_init(ramoops_init);
246module_exit(ramoops_exit);
247
248MODULE_LICENSE("GPL");
249MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
250MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
new file mode 100644
index 00000000000..341b1142bea
--- /dev/null
+++ b/drivers/char/scc.h
@@ -0,0 +1,613 @@
1/*
2 * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
3 *
4 * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 *
10 */
11
12
13#ifndef _SCC_H
14#define _SCC_H
15
16#include <linux/delay.h>
17
18/* Special configuration ioctls for the Atari SCC5380 Serial
19 * Communications Controller
20 */
21
22/* ioctl command codes */
23
24#define TIOCGATSCC 0x54c0 /* get SCC configuration */
25#define TIOCSATSCC 0x54c1 /* set SCC configuration */
26#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */
27
28/* Clock sources */
29
30#define CLK_RTxC 0
31#define CLK_TRxC 1
32#define CLK_PCLK 2
33
34/* baud_bases for the common clocks in the Atari. These are the real
35 * frequencies divided by 16.
36 */
37
38#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */
39#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */
40#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */
41#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */
42#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
43 * clock sources */
44
45/* The SCC clock configuration structure */
46
47struct scc_clock_config {
48 unsigned RTxC_base; /* base_baud of RTxC */
49 unsigned TRxC_base; /* base_baud of TRxC */
50 unsigned PCLK_base; /* base_baud of PCLK, both channels! */
51 struct {
52 unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
53 unsigned divisor; /* divisor for base baud, valid values:
54 * see below */
55 } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300,
56 * 600, 1200, 1800, 2400, 4800, 9600,
57 * 19200, 38400, 57600 and 115200 bps.
58 * The last two could be replaced by
59 * other rates > 38400 if they're not
60 * possible.
61 */
62};
63
64/* The following divisors are valid:
65 *
66 * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
67 * the BRG)
68 *
69 * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
70 *
71 * - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
72 *
73 */
74
75struct scc_port {
76 struct gs_port gs;
77 volatile unsigned char *ctrlp;
78 volatile unsigned char *datap;
79 int x_char; /* xon/xoff character */
80 int c_dcd;
81 int channel;
82 struct scc_port *port_a; /* Reference to port A and B */
83 struct scc_port *port_b; /* structs for reg access */
84};
85
86#define SCC_MAGIC 0x52696368
87
88/***********************************************************************/
89/* */
90/* Register Names */
91/* */
92/***********************************************************************/
93
94/* The SCC documentation gives no explicit names to the registers,
95 * they're just called WR0..15 and RR0..15. To make the source code
96 * better readable and make the transparent write reg read access (see
97 * below) possible, I christen them here with self-invented names.
98 * Note that (real) read registers are assigned numbers 16..31. WR7'
99 * has number 33.
100 */
101
102#define COMMAND_REG 0 /* wo */
103#define INT_AND_DMA_REG 1 /* wo */
104#define INT_VECTOR_REG 2 /* rw, common to both channels */
105#define RX_CTRL_REG 3 /* rw */
106#define AUX1_CTRL_REG 4 /* rw */
107#define TX_CTRL_REG 5 /* rw */
108#define SYNC_ADR_REG 6 /* wo */
109#define SYNC_CHAR_REG 7 /* wo */
110#define SDLC_OPTION_REG 33 /* wo */
111#define TX_DATA_REG 8 /* wo */
112#define MASTER_INT_CTRL 9 /* wo, common to both channels */
113#define AUX2_CTRL_REG 10 /* rw */
114#define CLK_CTRL_REG 11 /* wo */
115#define TIMER_LOW_REG 12 /* rw */
116#define TIMER_HIGH_REG 13 /* rw */
117#define DPLL_CTRL_REG 14 /* wo */
118#define INT_CTRL_REG 15 /* rw */
119
120#define STATUS_REG 16 /* ro */
121#define SPCOND_STATUS_REG 17 /* wo */
122/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
123#define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */
124#define INT_PENDING_REG 19 /* Channel A only! */
125/* RR4 is WR4, if b6(MR7') == 1 */
126/* RR5 is WR5, if b6(MR7') == 1 */
127#define FS_FIFO_LOW_REG 22 /* ro */
128#define FS_FIFO_HIGH_REG 23 /* ro */
129#define RX_DATA_REG 24 /* ro */
130/* RR9 is WR3, if b6(MR7') == 1 */
131#define DPLL_STATUS_REG 26 /* ro */
132/* RR11 is WR10, if b6(MR7') == 1 */
133/* RR12 is WR12 */
134/* RR13 is WR13 */
135/* RR14 not present */
136/* RR15 is WR15 */
137
138
139/***********************************************************************/
140/* */
141/* Register Values */
142/* */
143/***********************************************************************/
144
145
146/* WR0: COMMAND_REG "CR" */
147
148#define CR_RX_CRC_RESET 0x40
149#define CR_TX_CRC_RESET 0x80
150#define CR_TX_UNDERRUN_RESET 0xc0
151
152#define CR_EXTSTAT_RESET 0x10
153#define CR_SEND_ABORT 0x18
154#define CR_ENAB_INT_NEXT_RX 0x20
155#define CR_TX_PENDING_RESET 0x28
156#define CR_ERROR_RESET 0x30
157#define CR_HIGHEST_IUS_RESET 0x38
158
159
160/* WR1: INT_AND_DMA_REG "IDR" */
161
162#define IDR_EXTSTAT_INT_ENAB 0x01
163#define IDR_TX_INT_ENAB 0x02
164#define IDR_PARERR_AS_SPCOND 0x04
165
166#define IDR_RX_INT_DISAB 0x00
167#define IDR_RX_INT_FIRST 0x08
168#define IDR_RX_INT_ALL 0x10
169#define IDR_RX_INT_SPCOND 0x18
170#define IDR_RX_INT_MASK 0x18
171
172#define IDR_WAITREQ_RX 0x20
173#define IDR_WAITREQ_IS_REQ 0x40
174#define IDR_WAITREQ_ENAB 0x80
175
176
177/* WR3: RX_CTRL_REG "RCR" */
178
179#define RCR_RX_ENAB 0x01
180#define RCR_DISCARD_SYNC_CHARS 0x02
181#define RCR_ADDR_SEARCH 0x04
182#define RCR_CRC_ENAB 0x08
183#define RCR_SEARCH_MODE 0x10
184#define RCR_AUTO_ENAB_MODE 0x20
185
186#define RCR_CHSIZE_MASK 0xc0
187#define RCR_CHSIZE_5 0x00
188#define RCR_CHSIZE_6 0x40
189#define RCR_CHSIZE_7 0x80
190#define RCR_CHSIZE_8 0xc0
191
192
193/* WR4: AUX1_CTRL_REG "A1CR" */
194
195#define A1CR_PARITY_MASK 0x03
196#define A1CR_PARITY_NONE 0x00
197#define A1CR_PARITY_ODD 0x01
198#define A1CR_PARITY_EVEN 0x03
199
200#define A1CR_MODE_MASK 0x0c
201#define A1CR_MODE_SYNCR 0x00
202#define A1CR_MODE_ASYNC_1 0x04
203#define A1CR_MODE_ASYNC_15 0x08
204#define A1CR_MODE_ASYNC_2 0x0c
205
206#define A1CR_SYNCR_MODE_MASK 0x30
207#define A1CR_SYNCR_MONOSYNC 0x00
208#define A1CR_SYNCR_BISYNC 0x10
209#define A1CR_SYNCR_SDLC 0x20
210#define A1CR_SYNCR_EXTCSYNC 0x30
211
212#define A1CR_CLKMODE_MASK 0xc0
213#define A1CR_CLKMODE_x1 0x00
214#define A1CR_CLKMODE_x16 0x40
215#define A1CR_CLKMODE_x32 0x80
216#define A1CR_CLKMODE_x64 0xc0
217
218
219/* WR5: TX_CTRL_REG "TCR" */
220
221#define TCR_TX_CRC_ENAB 0x01
222#define TCR_RTS 0x02
223#define TCR_USE_CRC_CCITT 0x00
224#define TCR_USE_CRC_16 0x04
225#define TCR_TX_ENAB 0x08
226#define TCR_SEND_BREAK 0x10
227
228#define TCR_CHSIZE_MASK 0x60
229#define TCR_CHSIZE_5 0x00
230#define TCR_CHSIZE_6 0x20
231#define TCR_CHSIZE_7 0x40
232#define TCR_CHSIZE_8 0x60
233
234#define TCR_DTR 0x80
235
236
237/* WR7': SLDC_OPTION_REG "SOR" */
238
239#define SOR_AUTO_TX_ENAB 0x01
240#define SOR_AUTO_EOM_RESET 0x02
241#define SOR_AUTO_RTS_MODE 0x04
242#define SOR_NRZI_DISAB_HIGH 0x08
243#define SOR_ALT_DTRREQ_TIMING 0x10
244#define SOR_READ_CRC_CHARS 0x20
245#define SOR_EXTENDED_REG_ACCESS 0x40
246
247
248/* WR9: MASTER_INT_CTRL "MIC" */
249
250#define MIC_VEC_INCL_STAT 0x01
251#define MIC_NO_VECTOR 0x02
252#define MIC_DISAB_LOWER_CHAIN 0x04
253#define MIC_MASTER_INT_ENAB 0x08
254#define MIC_STATUS_HIGH 0x10
255#define MIC_IGN_INTACK 0x20
256
257#define MIC_NO_RESET 0x00
258#define MIC_CH_A_RESET 0x40
259#define MIC_CH_B_RESET 0x80
260#define MIC_HARD_RESET 0xc0
261
262
263/* WR10: AUX2_CTRL_REG "A2CR" */
264
265#define A2CR_SYNC_6 0x01
266#define A2CR_LOOP_MODE 0x02
267#define A2CR_ABORT_ON_UNDERRUN 0x04
268#define A2CR_MARK_IDLE 0x08
269#define A2CR_GO_ACTIVE_ON_POLL 0x10
270
271#define A2CR_CODING_MASK 0x60
272#define A2CR_CODING_NRZ 0x00
273#define A2CR_CODING_NRZI 0x20
274#define A2CR_CODING_FM1 0x40
275#define A2CR_CODING_FM0 0x60
276
277#define A2CR_PRESET_CRC_1 0x80
278
279
280/* WR11: CLK_CTRL_REG "CCR" */
281
282#define CCR_TRxCOUT_MASK 0x03
283#define CCR_TRxCOUT_XTAL 0x00
284#define CCR_TRxCOUT_TXCLK 0x01
285#define CCR_TRxCOUT_BRG 0x02
286#define CCR_TRxCOUT_DPLL 0x03
287
288#define CCR_TRxC_OUTPUT 0x04
289
290#define CCR_TXCLK_MASK 0x18
291#define CCR_TXCLK_RTxC 0x00
292#define CCR_TXCLK_TRxC 0x08
293#define CCR_TXCLK_BRG 0x10
294#define CCR_TXCLK_DPLL 0x18
295
296#define CCR_RXCLK_MASK 0x60
297#define CCR_RXCLK_RTxC 0x00
298#define CCR_RXCLK_TRxC 0x20
299#define CCR_RXCLK_BRG 0x40
300#define CCR_RXCLK_DPLL 0x60
301
302#define CCR_RTxC_XTAL 0x80
303
304
305/* WR14: DPLL_CTRL_REG "DCR" */
306
307#define DCR_BRG_ENAB 0x01
308#define DCR_BRG_USE_PCLK 0x02
309#define DCR_DTRREQ_IS_REQ 0x04
310#define DCR_AUTO_ECHO 0x08
311#define DCR_LOCAL_LOOPBACK 0x10
312
313#define DCR_DPLL_EDGE_SEARCH 0x20
314#define DCR_DPLL_ERR_RESET 0x40
315#define DCR_DPLL_DISAB 0x60
316#define DCR_DPLL_CLK_BRG 0x80
317#define DCR_DPLL_CLK_RTxC 0xa0
318#define DCR_DPLL_FM 0xc0
319#define DCR_DPLL_NRZI 0xe0
320
321
322/* WR15: INT_CTRL_REG "ICR" */
323
324#define ICR_OPTIONREG_SELECT 0x01
325#define ICR_ENAB_BRG_ZERO_INT 0x02
326#define ICR_USE_FS_FIFO 0x04
327#define ICR_ENAB_DCD_INT 0x08
328#define ICR_ENAB_SYNC_INT 0x10
329#define ICR_ENAB_CTS_INT 0x20
330#define ICR_ENAB_UNDERRUN_INT 0x40
331#define ICR_ENAB_BREAK_INT 0x80
332
333
334/* RR0: STATUS_REG "SR" */
335
336#define SR_CHAR_AVAIL 0x01
337#define SR_BRG_ZERO 0x02
338#define SR_TX_BUF_EMPTY 0x04
339#define SR_DCD 0x08
340#define SR_SYNC_ABORT 0x10
341#define SR_CTS 0x20
342#define SR_TX_UNDERRUN 0x40
343#define SR_BREAK 0x80
344
345
346/* RR1: SPCOND_STATUS_REG "SCSR" */
347
348#define SCSR_ALL_SENT 0x01
349#define SCSR_RESIDUAL_MASK 0x0e
350#define SCSR_PARITY_ERR 0x10
351#define SCSR_RX_OVERRUN 0x20
352#define SCSR_CRC_FRAME_ERR 0x40
353#define SCSR_END_OF_FRAME 0x80
354
355
356/* RR3: INT_PENDING_REG "IPR" */
357
358#define IPR_B_EXTSTAT 0x01
359#define IPR_B_TX 0x02
360#define IPR_B_RX 0x04
361#define IPR_A_EXTSTAT 0x08
362#define IPR_A_TX 0x10
363#define IPR_A_RX 0x20
364
365
366/* RR7: FS_FIFO_HIGH_REG "FFHR" */
367
368#define FFHR_CNT_MASK 0x3f
369#define FFHR_IS_FROM_FIFO 0x40
370#define FFHR_FIFO_OVERRUN 0x80
371
372
373/* RR10: DPLL_STATUS_REG "DSR" */
374
375#define DSR_ON_LOOP 0x02
376#define DSR_ON_LOOP_SENDING 0x10
377#define DSR_TWO_CLK_MISSING 0x40
378#define DSR_ONE_CLK_MISSING 0x80
379
380/***********************************************************************/
381/* */
382/* Register Access */
383/* */
384/***********************************************************************/
385
386
387/* The SCC needs 3.5 PCLK cycles recovery time between to register
388 * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
389 * 125 ns = 437.5 ns. This is too short for udelay().
390 * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
391 * quite right
392 */
393
394#define scc_reg_delay() \
395 do { \
396 if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \
397 __asm__ __volatile__ ( " nop; nop"); \
398 else if (MACH_IS_ATARI) \
399 __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
400 } while (0)
401
402static unsigned char scc_shadow[2][16];
403
404/* The following functions should relax the somehow complicated
405 * register access of the SCC. _SCCwrite() stores all written values
406 * (except for WR0 and WR8) in shadow registers for later recall. This
407 * removes the burden of remembering written values as needed. The
408 * extra work of storing the value doesn't count, since a delay is
409 * needed after a SCC access anyway. Additionally, _SCCwrite() manages
410 * writes to WR0 and WR8 differently, because these can be accessed
411 * directly with less overhead. Another special case are WR7 and WR7'.
412 * _SCCwrite automatically checks what of this registers is selected
413 * and changes b0 of WR15 if needed.
414 *
415 * _SCCread() for standard read registers is straightforward, except
416 * for RR2 (split into two "virtual" registers: one for the value
417 * written to WR2 (from the shadow) and one for the vector including
418 * status from RR2, Ch. B) and RR3. The latter must be read from
419 * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
420 * be accessed directly as before.
421 *
422 * The two inline function contain complicated switch statements. But
423 * I rely on regno and final_delay being constants, so gcc can reduce
424 * the whole stuff to just some assembler statements.
425 *
426 * _SCCwrite and _SCCread aren't intended to be used directly under
427 * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
428 * for that purpose. They assume that a local variable 'port' is
429 * declared and pointing to the port's scc_struct entry. The
430 * variants with "_NB" appended should be used if no other SCC
431 * accesses follow immediately (within 0.5 usecs). They just skip the
432 * final delay nops.
433 *
434 * Please note that accesses to SCC registers should only take place
435 * when interrupts are turned off (at least if SCC interrupts are
436 * enabled). Otherwise, an interrupt could interfere with the
437 * two-stage accessing process.
438 *
439 */
440
441
442static __inline__ void _SCCwrite(
443 struct scc_port *port,
444 unsigned char *shadow,
445 volatile unsigned char *_scc_del,
446 int regno,
447 unsigned char val, int final_delay )
448{
449 switch( regno ) {
450
451 case COMMAND_REG:
452 /* WR0 can be written directly without pointing */
453 *port->ctrlp = val;
454 break;
455
456 case SYNC_CHAR_REG:
457 /* For WR7, first set b0 of WR15 to 0, if needed */
458 if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
459 *port->ctrlp = 15;
460 shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
461 scc_reg_delay();
462 *port->ctrlp = shadow[INT_CTRL_REG];
463 scc_reg_delay();
464 }
465 goto normal_case;
466
467 case SDLC_OPTION_REG:
468 /* For WR7', first set b0 of WR15 to 1, if needed */
469 if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
470 *port->ctrlp = 15;
471 shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
472 scc_reg_delay();
473 *port->ctrlp = shadow[INT_CTRL_REG];
474 scc_reg_delay();
475 }
476 *port->ctrlp = 7;
477 shadow[8] = val; /* WR7' shadowed at WR8 */
478 scc_reg_delay();
479 *port->ctrlp = val;
480 break;
481
482 case TX_DATA_REG: /* WR8 */
483 /* TX_DATA_REG can be accessed directly on some h/w */
484 if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
485 {
486 *port->ctrlp = regno;
487 scc_reg_delay();
488 *port->ctrlp = val;
489 }
490 else
491 *port->datap = val;
492 break;
493
494 case MASTER_INT_CTRL:
495 *port->ctrlp = regno;
496 val &= 0x3f; /* bits 6..7 are the reset commands */
497 scc_shadow[0][regno] = val;
498 scc_reg_delay();
499 *port->ctrlp = val;
500 break;
501
502 case DPLL_CTRL_REG:
503 *port->ctrlp = regno;
504 val &= 0x1f; /* bits 5..7 are the DPLL commands */
505 shadow[regno] = val;
506 scc_reg_delay();
507 *port->ctrlp = val;
508 break;
509
510 case 1 ... 6:
511 case 10 ... 13:
512 case 15:
513 normal_case:
514 *port->ctrlp = regno;
515 shadow[regno] = val;
516 scc_reg_delay();
517 *port->ctrlp = val;
518 break;
519
520 default:
521 printk( "Bad SCC write access to WR%d\n", regno );
522 break;
523
524 }
525
526 if (final_delay)
527 scc_reg_delay();
528}
529
530
531static __inline__ unsigned char _SCCread(
532 struct scc_port *port,
533 unsigned char *shadow,
534 volatile unsigned char *_scc_del,
535 int regno, int final_delay )
536{
537 unsigned char rv;
538
539 switch( regno ) {
540
541 /* --- real read registers --- */
542 case STATUS_REG:
543 rv = *port->ctrlp;
544 break;
545
546 case INT_PENDING_REG:
547 /* RR3: read only from Channel A! */
548 port = port->port_a;
549 goto normal_case;
550
551 case RX_DATA_REG:
552 /* RR8 can be accessed directly on some h/w */
553 if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
554 {
555 *port->ctrlp = 8;
556 scc_reg_delay();
557 rv = *port->ctrlp;
558 }
559 else
560 rv = *port->datap;
561 break;
562
563 case CURR_VECTOR_REG:
564 /* RR2 (vector including status) from Ch. B */
565 port = port->port_b;
566 goto normal_case;
567
568 /* --- reading write registers: access the shadow --- */
569 case 1 ... 7:
570 case 10 ... 15:
571 return shadow[regno]; /* no final delay! */
572
573 /* WR7' is special, because it is shadowed at the place of WR8 */
574 case SDLC_OPTION_REG:
575 return shadow[8]; /* no final delay! */
576
577 /* WR9 is special too, because it is common for both channels */
578 case MASTER_INT_CTRL:
579 return scc_shadow[0][9]; /* no final delay! */
580
581 default:
582 printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
583 regno & ~16 );
584 break;
585
586 case SPCOND_STATUS_REG:
587 case FS_FIFO_LOW_REG:
588 case FS_FIFO_HIGH_REG:
589 case DPLL_STATUS_REG:
590 normal_case:
591 *port->ctrlp = regno & 0x0f;
592 scc_reg_delay();
593 rv = *port->ctrlp;
594 break;
595
596 }
597
598 if (final_delay)
599 scc_reg_delay();
600 return rv;
601}
602
603#define SCC_ACCESS_INIT(port) \
604 unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
605
606#define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
607#define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
608#define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1)
609#define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0)
610
611#define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or))
612
613#endif /* _SCC_H */
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
new file mode 100644
index 00000000000..0636520fa9b
--- /dev/null
+++ b/drivers/char/tpm/tpm_bios.c
@@ -0,0 +1,556 @@
1/*
2 * Copyright (C) 2005 IBM Corporation
3 *
4 * Authors:
5 * Seiji Munetoh <munetoh@jp.ibm.com>
6 * Stefan Berger <stefanb@us.ibm.com>
7 * Reiner Sailer <sailer@watson.ibm.com>
8 * Kylene Hall <kjhall@us.ibm.com>
9 *
10 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
11 *
12 * Access to the eventlog extended by the TCG BIOS of PC platform
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 */
20
21#include <linux/seq_file.h>
22#include <linux/fs.h>
23#include <linux/security.h>
24#include <linux/module.h>
25#include <linux/slab.h>
26#include <acpi/acpi.h>
27#include "tpm.h"
28
29#define TCG_EVENT_NAME_LEN_MAX 255
30#define MAX_TEXT_EVENT 1000 /* Max event string length */
31#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
32
33enum bios_platform_class {
34 BIOS_CLIENT = 0x00,
35 BIOS_SERVER = 0x01,
36};
37
38struct tpm_bios_log {
39 void *bios_event_log;
40 void *bios_event_log_end;
41};
42
43struct acpi_tcpa {
44 struct acpi_table_header hdr;
45 u16 platform_class;
46 union {
47 struct client_hdr {
48 u32 log_max_len __attribute__ ((packed));
49 u64 log_start_addr __attribute__ ((packed));
50 } client;
51 struct server_hdr {
52 u16 reserved;
53 u64 log_max_len __attribute__ ((packed));
54 u64 log_start_addr __attribute__ ((packed));
55 } server;
56 };
57};
58
59struct tcpa_event {
60 u32 pcr_index;
61 u32 event_type;
62 u8 pcr_value[20]; /* SHA1 */
63 u32 event_size;
64 u8 event_data[0];
65};
66
67enum tcpa_event_types {
68 PREBOOT = 0,
69 POST_CODE,
70 UNUSED,
71 NO_ACTION,
72 SEPARATOR,
73 ACTION,
74 EVENT_TAG,
75 SCRTM_CONTENTS,
76 SCRTM_VERSION,
77 CPU_MICROCODE,
78 PLATFORM_CONFIG_FLAGS,
79 TABLE_OF_DEVICES,
80 COMPACT_HASH,
81 IPL,
82 IPL_PARTITION_DATA,
83 NONHOST_CODE,
84 NONHOST_CONFIG,
85 NONHOST_INFO,
86};
87
88static const char* tcpa_event_type_strings[] = {
89 "PREBOOT",
90 "POST CODE",
91 "",
92 "NO ACTION",
93 "SEPARATOR",
94 "ACTION",
95 "EVENT TAG",
96 "S-CRTM Contents",
97 "S-CRTM Version",
98 "CPU Microcode",
99 "Platform Config Flags",
100 "Table of Devices",
101 "Compact Hash",
102 "IPL",
103 "IPL Partition Data",
104 "Non-Host Code",
105 "Non-Host Config",
106 "Non-Host Info"
107};
108
109struct tcpa_pc_event {
110 u32 event_id;
111 u32 event_size;
112 u8 event_data[0];
113};
114
115enum tcpa_pc_event_ids {
116 SMBIOS = 1,
117 BIS_CERT,
118 POST_BIOS_ROM,
119 ESCD,
120 CMOS,
121 NVRAM,
122 OPTION_ROM_EXEC,
123 OPTION_ROM_CONFIG,
124 OPTION_ROM_MICROCODE = 10,
125 S_CRTM_VERSION,
126 S_CRTM_CONTENTS,
127 POST_CONTENTS,
128 HOST_TABLE_OF_DEVICES,
129};
130
131static const char* tcpa_pc_event_id_strings[] = {
132 "",
133 "SMBIOS",
134 "BIS Certificate",
135 "POST BIOS ",
136 "ESCD ",
137 "CMOS",
138 "NVRAM",
139 "Option ROM",
140 "Option ROM config",
141 "",
142 "Option ROM microcode ",
143 "S-CRTM Version",
144 "S-CRTM Contents ",
145 "POST Contents ",
146 "Table of Devices",
147};
148
149/* returns pointer to start of pos. entry of tcg log */
150static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
151{
152 loff_t i;
153 struct tpm_bios_log *log = m->private;
154 void *addr = log->bios_event_log;
155 void *limit = log->bios_event_log_end;
156 struct tcpa_event *event;
157
158 /* read over *pos measurements */
159 for (i = 0; i < *pos; i++) {
160 event = addr;
161
162 if ((addr + sizeof(struct tcpa_event)) < limit) {
163 if (event->event_type == 0 && event->event_size == 0)
164 return NULL;
165 addr += sizeof(struct tcpa_event) + event->event_size;
166 }
167 }
168
169 /* now check if current entry is valid */
170 if ((addr + sizeof(struct tcpa_event)) >= limit)
171 return NULL;
172
173 event = addr;
174
175 if ((event->event_type == 0 && event->event_size == 0) ||
176 ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
177 return NULL;
178
179 return addr;
180}
181
182static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
183 loff_t *pos)
184{
185 struct tcpa_event *event = v;
186 struct tpm_bios_log *log = m->private;
187 void *limit = log->bios_event_log_end;
188
189 v += sizeof(struct tcpa_event) + event->event_size;
190
191 /* now check if current entry is valid */
192 if ((v + sizeof(struct tcpa_event)) >= limit)
193 return NULL;
194
195 event = v;
196
197 if (event->event_type == 0 && event->event_size == 0)
198 return NULL;
199
200 if ((event->event_type == 0 && event->event_size == 0) ||
201 ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
202 return NULL;
203
204 (*pos)++;
205 return v;
206}
207
208static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
209{
210}
211
212static int get_event_name(char *dest, struct tcpa_event *event,
213 unsigned char * event_entry)
214{
215 const char *name = "";
216 /* 41 so there is room for 40 data and 1 nul */
217 char data[41] = "";
218 int i, n_len = 0, d_len = 0;
219 struct tcpa_pc_event *pc_event;
220
221 switch(event->event_type) {
222 case PREBOOT:
223 case POST_CODE:
224 case UNUSED:
225 case NO_ACTION:
226 case SCRTM_CONTENTS:
227 case SCRTM_VERSION:
228 case CPU_MICROCODE:
229 case PLATFORM_CONFIG_FLAGS:
230 case TABLE_OF_DEVICES:
231 case COMPACT_HASH:
232 case IPL:
233 case IPL_PARTITION_DATA:
234 case NONHOST_CODE:
235 case NONHOST_CONFIG:
236 case NONHOST_INFO:
237 name = tcpa_event_type_strings[event->event_type];
238 n_len = strlen(name);
239 break;
240 case SEPARATOR:
241 case ACTION:
242 if (MAX_TEXT_EVENT > event->event_size) {
243 name = event_entry;
244 n_len = event->event_size;
245 }
246 break;
247 case EVENT_TAG:
248 pc_event = (struct tcpa_pc_event *)event_entry;
249
250 /* ToDo Row data -> Base64 */
251
252 switch (pc_event->event_id) {
253 case SMBIOS:
254 case BIS_CERT:
255 case CMOS:
256 case NVRAM:
257 case OPTION_ROM_EXEC:
258 case OPTION_ROM_CONFIG:
259 case S_CRTM_VERSION:
260 name = tcpa_pc_event_id_strings[pc_event->event_id];
261 n_len = strlen(name);
262 break;
263 /* hash data */
264 case POST_BIOS_ROM:
265 case ESCD:
266 case OPTION_ROM_MICROCODE:
267 case S_CRTM_CONTENTS:
268 case POST_CONTENTS:
269 name = tcpa_pc_event_id_strings[pc_event->event_id];
270 n_len = strlen(name);
271 for (i = 0; i < 20; i++)
272 d_len += sprintf(&data[2*i], "%02x",
273 pc_event->event_data[i]);
274 break;
275 default:
276 break;
277 }
278 default:
279 break;
280 }
281
282 return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
283 n_len, name, d_len, data);
284
285}
286
287static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
288{
289 struct tcpa_event *event = v;
290 char *data = v;
291 int i;
292
293 for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
294 seq_putc(m, data[i]);
295
296 return 0;
297}
298
299static int tpm_bios_measurements_release(struct inode *inode,
300 struct file *file)
301{
302 struct seq_file *seq = file->private_data;
303 struct tpm_bios_log *log = seq->private;
304
305 if (log) {
306 kfree(log->bios_event_log);
307 kfree(log);
308 }
309
310 return seq_release(inode, file);
311}
312
313static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
314{
315 int len = 0;
316 int i;
317 char *eventname;
318 struct tcpa_event *event = v;
319 unsigned char *event_entry =
320 (unsigned char *) (v + sizeof(struct tcpa_event));
321
322 eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
323 if (!eventname) {
324 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
325 __func__);
326 return -EFAULT;
327 }
328
329 seq_printf(m, "%2d ", event->pcr_index);
330
331 /* 2nd: SHA1 */
332 for (i = 0; i < 20; i++)
333 seq_printf(m, "%02x", event->pcr_value[i]);
334
335 /* 3rd: event type identifier */
336 seq_printf(m, " %02x", event->event_type);
337
338 len += get_event_name(eventname, event, event_entry);
339
340 /* 4th: eventname <= max + \'0' delimiter */
341 seq_printf(m, " %s\n", eventname);
342
343 kfree(eventname);
344 return 0;
345}
346
347static const struct seq_operations tpm_ascii_b_measurments_seqops = {
348 .start = tpm_bios_measurements_start,
349 .next = tpm_bios_measurements_next,
350 .stop = tpm_bios_measurements_stop,
351 .show = tpm_ascii_bios_measurements_show,
352};
353
354static const struct seq_operations tpm_binary_b_measurments_seqops = {
355 .start = tpm_bios_measurements_start,
356 .next = tpm_bios_measurements_next,
357 .stop = tpm_bios_measurements_stop,
358 .show = tpm_binary_bios_measurements_show,
359};
360
361/* read binary bios log */
362static int read_log(struct tpm_bios_log *log)
363{
364 struct acpi_tcpa *buff;
365 acpi_status status;
366 struct acpi_table_header *virt;
367 u64 len, start;
368
369 if (log->bios_event_log != NULL) {
370 printk(KERN_ERR
371 "%s: ERROR - Eventlog already initialized\n",
372 __func__);
373 return -EFAULT;
374 }
375
376 /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
377 status = acpi_get_table(ACPI_SIG_TCPA, 1,
378 (struct acpi_table_header **)&buff);
379
380 if (ACPI_FAILURE(status)) {
381 printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
382 __func__);
383 return -EIO;
384 }
385
386 switch(buff->platform_class) {
387 case BIOS_SERVER:
388 len = buff->server.log_max_len;
389 start = buff->server.log_start_addr;
390 break;
391 case BIOS_CLIENT:
392 default:
393 len = buff->client.log_max_len;
394 start = buff->client.log_start_addr;
395 break;
396 }
397 if (!len) {
398 printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
399 return -EIO;
400 }
401
402 /* malloc EventLog space */
403 log->bios_event_log = kmalloc(len, GFP_KERNEL);
404 if (!log->bios_event_log) {
405 printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
406 __func__);
407 return -ENOMEM;
408 }
409
410 log->bios_event_log_end = log->bios_event_log + len;
411
412 virt = acpi_os_map_memory(start, len);
413
414 memcpy(log->bios_event_log, virt, len);
415
416 acpi_os_unmap_memory(virt, len);
417 return 0;
418}
419
420static int tpm_ascii_bios_measurements_open(struct inode *inode,
421 struct file *file)
422{
423 int err;
424 struct tpm_bios_log *log;
425 struct seq_file *seq;
426
427 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
428 if (!log)
429 return -ENOMEM;
430
431 if ((err = read_log(log)))
432 goto out_free;
433
434 /* now register seq file */
435 err = seq_open(file, &tpm_ascii_b_measurments_seqops);
436 if (!err) {
437 seq = file->private_data;
438 seq->private = log;
439 } else {
440 goto out_free;
441 }
442
443out:
444 return err;
445out_free:
446 kfree(log->bios_event_log);
447 kfree(log);
448 goto out;
449}
450
451static const struct file_operations tpm_ascii_bios_measurements_ops = {
452 .open = tpm_ascii_bios_measurements_open,
453 .read = seq_read,
454 .llseek = seq_lseek,
455 .release = tpm_bios_measurements_release,
456};
457
458static int tpm_binary_bios_measurements_open(struct inode *inode,
459 struct file *file)
460{
461 int err;
462 struct tpm_bios_log *log;
463 struct seq_file *seq;
464
465 log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
466 if (!log)
467 return -ENOMEM;
468
469 if ((err = read_log(log)))
470 goto out_free;
471
472 /* now register seq file */
473 err = seq_open(file, &tpm_binary_b_measurments_seqops);
474 if (!err) {
475 seq = file->private_data;
476 seq->private = log;
477 } else {
478 goto out_free;
479 }
480
481out:
482 return err;
483out_free:
484 kfree(log->bios_event_log);
485 kfree(log);
486 goto out;
487}
488
489static const struct file_operations tpm_binary_bios_measurements_ops = {
490 .open = tpm_binary_bios_measurements_open,
491 .read = seq_read,
492 .llseek = seq_lseek,
493 .release = tpm_bios_measurements_release,
494};
495
496static int is_bad(void *p)
497{
498 if (!p)
499 return 1;
500 if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
501 return 1;
502 return 0;
503}
504
505struct dentry **tpm_bios_log_setup(char *name)
506{
507 struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
508
509 tpm_dir = securityfs_create_dir(name, NULL);
510 if (is_bad(tpm_dir))
511 goto out;
512
513 bin_file =
514 securityfs_create_file("binary_bios_measurements",
515 S_IRUSR | S_IRGRP, tpm_dir, NULL,
516 &tpm_binary_bios_measurements_ops);
517 if (is_bad(bin_file))
518 goto out_tpm;
519
520 ascii_file =
521 securityfs_create_file("ascii_bios_measurements",
522 S_IRUSR | S_IRGRP, tpm_dir, NULL,
523 &tpm_ascii_bios_measurements_ops);
524 if (is_bad(ascii_file))
525 goto out_bin;
526
527 ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
528 if (!ret)
529 goto out_ascii;
530
531 ret[0] = ascii_file;
532 ret[1] = bin_file;
533 ret[2] = tpm_dir;
534
535 return ret;
536
537out_ascii:
538 securityfs_remove(ascii_file);
539out_bin:
540 securityfs_remove(bin_file);
541out_tpm:
542 securityfs_remove(tpm_dir);
543out:
544 return NULL;
545}
546EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
547
548void tpm_bios_log_teardown(struct dentry **lst)
549{
550 int i;
551
552 for (i = 0; i < 3; i++)
553 securityfs_remove(lst[i]);
554}
555EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
556MODULE_LICENSE("GPL");
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
new file mode 100644
index 00000000000..ad6e64a2912
--- /dev/null
+++ b/drivers/char/viotape.c
@@ -0,0 +1,1041 @@
1/* -*- linux-c -*-
2 * drivers/char/viotape.c
3 *
4 * iSeries Virtual Tape
5 *
6 * Authors: Dave Boutcher <boutcher@us.ibm.com>
7 * Ryan Arnold <ryanarn@us.ibm.com>
8 * Colin Devilbiss <devilbis@us.ibm.com>
9 * Stephen Rothwell
10 *
11 * (C) Copyright 2000-2004 IBM Corporation
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) anyu later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * This routine provides access to tape drives owned and managed by an OS/400
28 * partition running on the same box as this Linux partition.
29 *
30 * All tape operations are performed by sending messages back and forth to
31 * the OS/400 partition. The format of the messages is defined in
32 * iseries/vio.h
33 */
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/errno.h>
37#include <linux/init.h>
38#include <linux/wait.h>
39#include <linux/spinlock.h>
40#include <linux/mtio.h>
41#include <linux/device.h>
42#include <linux/dma-mapping.h>
43#include <linux/fs.h>
44#include <linux/cdev.h>
45#include <linux/major.h>
46#include <linux/completion.h>
47#include <linux/proc_fs.h>
48#include <linux/seq_file.h>
49#include <linux/mutex.h>
50#include <linux/slab.h>
51
52#include <asm/uaccess.h>
53#include <asm/ioctls.h>
54#include <asm/firmware.h>
55#include <asm/vio.h>
56#include <asm/iseries/vio.h>
57#include <asm/iseries/hv_lp_event.h>
58#include <asm/iseries/hv_call_event.h>
59#include <asm/iseries/hv_lp_config.h>
60
61#define VIOTAPE_VERSION "1.2"
62#define VIOTAPE_MAXREQ 1
63
64#define VIOTAPE_KERN_WARN KERN_WARNING "viotape: "
65#define VIOTAPE_KERN_INFO KERN_INFO "viotape: "
66
67static DEFINE_MUTEX(proc_viotape_mutex);
68static int viotape_numdev;
69
70/*
71 * The minor number follows the conventions of the SCSI tape drives. The
72 * rewind and mode are encoded in the minor #. We use this struct to break
73 * them out
74 */
75struct viot_devinfo_struct {
76 int devno;
77 int mode;
78 int rewind;
79};
80
81#define VIOTAPOP_RESET 0
82#define VIOTAPOP_FSF 1
83#define VIOTAPOP_BSF 2
84#define VIOTAPOP_FSR 3
85#define VIOTAPOP_BSR 4
86#define VIOTAPOP_WEOF 5
87#define VIOTAPOP_REW 6
88#define VIOTAPOP_NOP 7
89#define VIOTAPOP_EOM 8
90#define VIOTAPOP_ERASE 9
91#define VIOTAPOP_SETBLK 10
92#define VIOTAPOP_SETDENSITY 11
93#define VIOTAPOP_SETPOS 12
94#define VIOTAPOP_GETPOS 13
95#define VIOTAPOP_SETPART 14
96#define VIOTAPOP_UNLOAD 15
97
98enum viotaperc {
99 viotape_InvalidRange = 0x0601,
100 viotape_InvalidToken = 0x0602,
101 viotape_DMAError = 0x0603,
102 viotape_UseError = 0x0604,
103 viotape_ReleaseError = 0x0605,
104 viotape_InvalidTape = 0x0606,
105 viotape_InvalidOp = 0x0607,
106 viotape_TapeErr = 0x0608,
107
108 viotape_AllocTimedOut = 0x0640,
109 viotape_BOTEnc = 0x0641,
110 viotape_BlankTape = 0x0642,
111 viotape_BufferEmpty = 0x0643,
112 viotape_CleanCartFound = 0x0644,
113 viotape_CmdNotAllowed = 0x0645,
114 viotape_CmdNotSupported = 0x0646,
115 viotape_DataCheck = 0x0647,
116 viotape_DecompressErr = 0x0648,
117 viotape_DeviceTimeout = 0x0649,
118 viotape_DeviceUnavail = 0x064a,
119 viotape_DeviceBusy = 0x064b,
120 viotape_EndOfMedia = 0x064c,
121 viotape_EndOfTape = 0x064d,
122 viotape_EquipCheck = 0x064e,
123 viotape_InsufficientRs = 0x064f,
124 viotape_InvalidLogBlk = 0x0650,
125 viotape_LengthError = 0x0651,
126 viotape_LibDoorOpen = 0x0652,
127 viotape_LoadFailure = 0x0653,
128 viotape_NotCapable = 0x0654,
129 viotape_NotOperational = 0x0655,
130 viotape_NotReady = 0x0656,
131 viotape_OpCancelled = 0x0657,
132 viotape_PhyLinkErr = 0x0658,
133 viotape_RdyNotBOT = 0x0659,
134 viotape_TapeMark = 0x065a,
135 viotape_WriteProt = 0x065b
136};
137
138static const struct vio_error_entry viotape_err_table[] = {
139 { viotape_InvalidRange, EIO, "Internal error" },
140 { viotape_InvalidToken, EIO, "Internal error" },
141 { viotape_DMAError, EIO, "DMA error" },
142 { viotape_UseError, EIO, "Internal error" },
143 { viotape_ReleaseError, EIO, "Internal error" },
144 { viotape_InvalidTape, EIO, "Invalid tape device" },
145 { viotape_InvalidOp, EIO, "Invalid operation" },
146 { viotape_TapeErr, EIO, "Tape error" },
147 { viotape_AllocTimedOut, EBUSY, "Allocate timed out" },
148 { viotape_BOTEnc, EIO, "Beginning of tape encountered" },
149 { viotape_BlankTape, EIO, "Blank tape" },
150 { viotape_BufferEmpty, EIO, "Buffer empty" },
151 { viotape_CleanCartFound, ENOMEDIUM, "Cleaning cartridge found" },
152 { viotape_CmdNotAllowed, EIO, "Command not allowed" },
153 { viotape_CmdNotSupported, EIO, "Command not supported" },
154 { viotape_DataCheck, EIO, "Data check" },
155 { viotape_DecompressErr, EIO, "Decompression error" },
156 { viotape_DeviceTimeout, EBUSY, "Device timeout" },
157 { viotape_DeviceUnavail, EIO, "Device unavailable" },
158 { viotape_DeviceBusy, EBUSY, "Device busy" },
159 { viotape_EndOfMedia, ENOSPC, "End of media" },
160 { viotape_EndOfTape, ENOSPC, "End of tape" },
161 { viotape_EquipCheck, EIO, "Equipment check" },
162 { viotape_InsufficientRs, EOVERFLOW, "Insufficient tape resources" },
163 { viotape_InvalidLogBlk, EIO, "Invalid logical block location" },
164 { viotape_LengthError, EOVERFLOW, "Length error" },
165 { viotape_LibDoorOpen, EBUSY, "Door open" },
166 { viotape_LoadFailure, ENOMEDIUM, "Load failure" },
167 { viotape_NotCapable, EIO, "Not capable" },
168 { viotape_NotOperational, EIO, "Not operational" },
169 { viotape_NotReady, EIO, "Not ready" },
170 { viotape_OpCancelled, EIO, "Operation cancelled" },
171 { viotape_PhyLinkErr, EIO, "Physical link error" },
172 { viotape_RdyNotBOT, EIO, "Ready but not beginning of tape" },
173 { viotape_TapeMark, EIO, "Tape mark" },
174 { viotape_WriteProt, EROFS, "Write protection error" },
175 { 0, 0, NULL },
176};
177
178/* Maximum number of tapes we support */
179#define VIOTAPE_MAX_TAPE HVMAXARCHITECTEDVIRTUALTAPES
180#define MAX_PARTITIONS 4
181
182/* defines for current tape state */
183#define VIOT_IDLE 0
184#define VIOT_READING 1
185#define VIOT_WRITING 2
186
187/* Our info on the tapes */
188static struct {
189 const char *rsrcname;
190 const char *type;
191 const char *model;
192} viotape_unitinfo[VIOTAPE_MAX_TAPE];
193
194static struct mtget viomtget[VIOTAPE_MAX_TAPE];
195
196static struct class *tape_class;
197
198static struct device *tape_device[VIOTAPE_MAX_TAPE];
199
200/*
201 * maintain the current state of each tape (and partition)
202 * so that we know when to write EOF marks.
203 */
204static struct {
205 unsigned char cur_part;
206 unsigned char part_stat_rwi[MAX_PARTITIONS];
207} state[VIOTAPE_MAX_TAPE];
208
209/* We single-thread */
210static struct semaphore reqSem;
211
212/*
213 * When we send a request, we use this struct to get the response back
214 * from the interrupt handler
215 */
216struct op_struct {
217 void *buffer;
218 dma_addr_t dmaaddr;
219 size_t count;
220 int rc;
221 int non_blocking;
222 struct completion com;
223 struct device *dev;
224 struct op_struct *next;
225};
226
227static spinlock_t op_struct_list_lock;
228static struct op_struct *op_struct_list;
229
230/* forward declaration to resolve interdependence */
231static int chg_state(int index, unsigned char new_state, struct file *file);
232
233/* procfs support */
234static int proc_viotape_show(struct seq_file *m, void *v)
235{
236 int i;
237
238 seq_printf(m, "viotape driver version " VIOTAPE_VERSION "\n");
239 for (i = 0; i < viotape_numdev; i++) {
240 seq_printf(m, "viotape device %d is iSeries resource %10.10s"
241 "type %4.4s, model %3.3s\n",
242 i, viotape_unitinfo[i].rsrcname,
243 viotape_unitinfo[i].type,
244 viotape_unitinfo[i].model);
245 }
246 return 0;
247}
248
249static int proc_viotape_open(struct inode *inode, struct file *file)
250{
251 return single_open(file, proc_viotape_show, NULL);
252}
253
254static const struct file_operations proc_viotape_operations = {
255 .owner = THIS_MODULE,
256 .open = proc_viotape_open,
257 .read = seq_read,
258 .llseek = seq_lseek,
259 .release = single_release,
260};
261
262/* Decode the device minor number into its parts */
263void get_dev_info(struct inode *ino, struct viot_devinfo_struct *devi)
264{
265 devi->devno = iminor(ino) & 0x1F;
266 devi->mode = (iminor(ino) & 0x60) >> 5;
267 /* if bit is set in the minor, do _not_ rewind automatically */
268 devi->rewind = (iminor(ino) & 0x80) == 0;
269}
270
271/* This is called only from the exit and init paths, so no need for locking */
272static void clear_op_struct_pool(void)
273{
274 while (op_struct_list) {
275 struct op_struct *toFree = op_struct_list;
276 op_struct_list = op_struct_list->next;
277 kfree(toFree);
278 }
279}
280
281/* Likewise, this is only called from the init path */
282static int add_op_structs(int structs)
283{
284 int i;
285
286 for (i = 0; i < structs; ++i) {
287 struct op_struct *new_struct =
288 kmalloc(sizeof(*new_struct), GFP_KERNEL);
289 if (!new_struct) {
290 clear_op_struct_pool();
291 return -ENOMEM;
292 }
293 new_struct->next = op_struct_list;
294 op_struct_list = new_struct;
295 }
296 return 0;
297}
298
299/* Allocate an op structure from our pool */
300static struct op_struct *get_op_struct(void)
301{
302 struct op_struct *retval;
303 unsigned long flags;
304
305 spin_lock_irqsave(&op_struct_list_lock, flags);
306 retval = op_struct_list;
307 if (retval)
308 op_struct_list = retval->next;
309 spin_unlock_irqrestore(&op_struct_list_lock, flags);
310 if (retval) {
311 memset(retval, 0, sizeof(*retval));
312 init_completion(&retval->com);
313 }
314
315 return retval;
316}
317
318/* Return an op structure to our pool */
319static void free_op_struct(struct op_struct *op_struct)
320{
321 unsigned long flags;
322
323 spin_lock_irqsave(&op_struct_list_lock, flags);
324 op_struct->next = op_struct_list;
325 op_struct_list = op_struct;
326 spin_unlock_irqrestore(&op_struct_list_lock, flags);
327}
328
329/* Map our tape return codes to errno values */
330int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
331{
332 const struct vio_error_entry *err;
333
334 if (tape_rc == 0)
335 return 0;
336
337 err = vio_lookup_rc(viotape_err_table, tape_rc);
338 printk(VIOTAPE_KERN_WARN "error(%s) 0x%04x on Device %d (%-10s): %s\n",
339 operation, tape_rc, tapeno,
340 viotape_unitinfo[tapeno].rsrcname, err->msg);
341 return -err->errno;
342}
343
344/* Write */
345static ssize_t viotap_write(struct file *file, const char *buf,
346 size_t count, loff_t * ppos)
347{
348 HvLpEvent_Rc hvrc;
349 unsigned short flags = file->f_flags;
350 int noblock = ((flags & O_NONBLOCK) != 0);
351 ssize_t ret;
352 struct viot_devinfo_struct devi;
353 struct op_struct *op = get_op_struct();
354
355 if (op == NULL)
356 return -ENOMEM;
357
358 get_dev_info(file->f_path.dentry->d_inode, &devi);
359
360 /*
361 * We need to make sure we can send a request. We use
362 * a semaphore to keep track of # requests in use. If
363 * we are non-blocking, make sure we don't block on the
364 * semaphore
365 */
366 if (noblock) {
367 if (down_trylock(&reqSem)) {
368 ret = -EWOULDBLOCK;
369 goto free_op;
370 }
371 } else
372 down(&reqSem);
373
374 /* Allocate a DMA buffer */
375 op->dev = tape_device[devi.devno];
376 op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
377 GFP_ATOMIC);
378
379 if (op->buffer == NULL) {
380 printk(VIOTAPE_KERN_WARN
381 "error allocating dma buffer for len %ld\n",
382 count);
383 ret = -EFAULT;
384 goto up_sem;
385 }
386
387 /* Copy the data into the buffer */
388 if (copy_from_user(op->buffer, buf, count)) {
389 printk(VIOTAPE_KERN_WARN "tape: error on copy from user\n");
390 ret = -EFAULT;
391 goto free_dma;
392 }
393
394 op->non_blocking = noblock;
395 init_completion(&op->com);
396 op->count = count;
397
398 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
399 HvLpEvent_Type_VirtualIo,
400 viomajorsubtype_tape | viotapewrite,
401 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
402 viopath_sourceinst(viopath_hostLp),
403 viopath_targetinst(viopath_hostLp),
404 (u64)(unsigned long)op, VIOVERSION << 16,
405 ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
406 if (hvrc != HvLpEvent_Rc_Good) {
407 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
408 (int)hvrc);
409 ret = -EIO;
410 goto free_dma;
411 }
412
413 if (noblock)
414 return count;
415
416 wait_for_completion(&op->com);
417
418 if (op->rc)
419 ret = tape_rc_to_errno(op->rc, "write", devi.devno);
420 else {
421 chg_state(devi.devno, VIOT_WRITING, file);
422 ret = op->count;
423 }
424
425free_dma:
426 dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
427up_sem:
428 up(&reqSem);
429free_op:
430 free_op_struct(op);
431 return ret;
432}
433
434/* read */
435static ssize_t viotap_read(struct file *file, char *buf, size_t count,
436 loff_t *ptr)
437{
438 HvLpEvent_Rc hvrc;
439 unsigned short flags = file->f_flags;
440 struct op_struct *op = get_op_struct();
441 int noblock = ((flags & O_NONBLOCK) != 0);
442 ssize_t ret;
443 struct viot_devinfo_struct devi;
444
445 if (op == NULL)
446 return -ENOMEM;
447
448 get_dev_info(file->f_path.dentry->d_inode, &devi);
449
450 /*
451 * We need to make sure we can send a request. We use
452 * a semaphore to keep track of # requests in use. If
453 * we are non-blocking, make sure we don't block on the
454 * semaphore
455 */
456 if (noblock) {
457 if (down_trylock(&reqSem)) {
458 ret = -EWOULDBLOCK;
459 goto free_op;
460 }
461 } else
462 down(&reqSem);
463
464 chg_state(devi.devno, VIOT_READING, file);
465
466 /* Allocate a DMA buffer */
467 op->dev = tape_device[devi.devno];
468 op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
469 GFP_ATOMIC);
470 if (op->buffer == NULL) {
471 ret = -EFAULT;
472 goto up_sem;
473 }
474
475 op->count = count;
476 init_completion(&op->com);
477
478 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
479 HvLpEvent_Type_VirtualIo,
480 viomajorsubtype_tape | viotaperead,
481 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
482 viopath_sourceinst(viopath_hostLp),
483 viopath_targetinst(viopath_hostLp),
484 (u64)(unsigned long)op, VIOVERSION << 16,
485 ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
486 if (hvrc != HvLpEvent_Rc_Good) {
487 printk(VIOTAPE_KERN_WARN "tape hv error on op %d\n",
488 (int)hvrc);
489 ret = -EIO;
490 goto free_dma;
491 }
492
493 wait_for_completion(&op->com);
494
495 if (op->rc)
496 ret = tape_rc_to_errno(op->rc, "read", devi.devno);
497 else {
498 ret = op->count;
499 if (ret && copy_to_user(buf, op->buffer, ret)) {
500 printk(VIOTAPE_KERN_WARN "error on copy_to_user\n");
501 ret = -EFAULT;
502 }
503 }
504
505free_dma:
506 dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
507up_sem:
508 up(&reqSem);
509free_op:
510 free_op_struct(op);
511 return ret;
512}
513
514/* ioctl */
515static int viotap_ioctl(struct inode *inode, struct file *file,
516 unsigned int cmd, unsigned long arg)
517{
518 HvLpEvent_Rc hvrc;
519 int ret;
520 struct viot_devinfo_struct devi;
521 struct mtop mtc;
522 u32 myOp;
523 struct op_struct *op = get_op_struct();
524
525 if (op == NULL)
526 return -ENOMEM;
527
528 get_dev_info(file->f_path.dentry->d_inode, &devi);
529
530 down(&reqSem);
531
532 ret = -EINVAL;
533
534 switch (cmd) {
535 case MTIOCTOP:
536 ret = -EFAULT;
537 /*
538 * inode is null if and only if we (the kernel)
539 * made the request
540 */
541 if (inode == NULL)
542 memcpy(&mtc, (void *) arg, sizeof(struct mtop));
543 else if (copy_from_user((char *)&mtc, (char *)arg,
544 sizeof(struct mtop)))
545 goto free_op;
546
547 ret = -EIO;
548 switch (mtc.mt_op) {
549 case MTRESET:
550 myOp = VIOTAPOP_RESET;
551 break;
552 case MTFSF:
553 myOp = VIOTAPOP_FSF;
554 break;
555 case MTBSF:
556 myOp = VIOTAPOP_BSF;
557 break;
558 case MTFSR:
559 myOp = VIOTAPOP_FSR;
560 break;
561 case MTBSR:
562 myOp = VIOTAPOP_BSR;
563 break;
564 case MTWEOF:
565 myOp = VIOTAPOP_WEOF;
566 break;
567 case MTREW:
568 myOp = VIOTAPOP_REW;
569 break;
570 case MTNOP:
571 myOp = VIOTAPOP_NOP;
572 break;
573 case MTEOM:
574 myOp = VIOTAPOP_EOM;
575 break;
576 case MTERASE:
577 myOp = VIOTAPOP_ERASE;
578 break;
579 case MTSETBLK:
580 myOp = VIOTAPOP_SETBLK;
581 break;
582 case MTSETDENSITY:
583 myOp = VIOTAPOP_SETDENSITY;
584 break;
585 case MTTELL:
586 myOp = VIOTAPOP_GETPOS;
587 break;
588 case MTSEEK:
589 myOp = VIOTAPOP_SETPOS;
590 break;
591 case MTSETPART:
592 myOp = VIOTAPOP_SETPART;
593 break;
594 case MTOFFL:
595 myOp = VIOTAPOP_UNLOAD;
596 break;
597 default:
598 printk(VIOTAPE_KERN_WARN "MTIOCTOP called "
599 "with invalid op 0x%x\n", mtc.mt_op);
600 goto free_op;
601 }
602
603 /*
604 * if we moved the head, we are no longer
605 * reading or writing
606 */
607 switch (mtc.mt_op) {
608 case MTFSF:
609 case MTBSF:
610 case MTFSR:
611 case MTBSR:
612 case MTTELL:
613 case MTSEEK:
614 case MTREW:
615 chg_state(devi.devno, VIOT_IDLE, file);
616 }
617
618 init_completion(&op->com);
619 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
620 HvLpEvent_Type_VirtualIo,
621 viomajorsubtype_tape | viotapeop,
622 HvLpEvent_AckInd_DoAck,
623 HvLpEvent_AckType_ImmediateAck,
624 viopath_sourceinst(viopath_hostLp),
625 viopath_targetinst(viopath_hostLp),
626 (u64)(unsigned long)op,
627 VIOVERSION << 16,
628 ((u64)devi.devno << 48), 0,
629 (((u64)myOp) << 32) | mtc.mt_count, 0);
630 if (hvrc != HvLpEvent_Rc_Good) {
631 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
632 (int)hvrc);
633 goto free_op;
634 }
635 wait_for_completion(&op->com);
636 ret = tape_rc_to_errno(op->rc, "tape operation", devi.devno);
637 goto free_op;
638
639 case MTIOCGET:
640 ret = -EIO;
641 init_completion(&op->com);
642 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
643 HvLpEvent_Type_VirtualIo,
644 viomajorsubtype_tape | viotapegetstatus,
645 HvLpEvent_AckInd_DoAck,
646 HvLpEvent_AckType_ImmediateAck,
647 viopath_sourceinst(viopath_hostLp),
648 viopath_targetinst(viopath_hostLp),
649 (u64)(unsigned long)op, VIOVERSION << 16,
650 ((u64)devi.devno << 48), 0, 0, 0);
651 if (hvrc != HvLpEvent_Rc_Good) {
652 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
653 (int)hvrc);
654 goto free_op;
655 }
656 wait_for_completion(&op->com);
657
658 /* Operation is complete - grab the error code */
659 ret = tape_rc_to_errno(op->rc, "get status", devi.devno);
660 free_op_struct(op);
661 up(&reqSem);
662
663 if ((ret == 0) && copy_to_user((void *)arg,
664 &viomtget[devi.devno],
665 sizeof(viomtget[0])))
666 ret = -EFAULT;
667 return ret;
668 case MTIOCPOS:
669 printk(VIOTAPE_KERN_WARN "Got an (unsupported) MTIOCPOS\n");
670 break;
671 default:
672 printk(VIOTAPE_KERN_WARN "got an unsupported ioctl 0x%0x\n",
673 cmd);
674 break;
675 }
676
677free_op:
678 free_op_struct(op);
679 up(&reqSem);
680 return ret;
681}
682
683static long viotap_unlocked_ioctl(struct file *file,
684 unsigned int cmd, unsigned long arg)
685{
686 long rc;
687
688 mutex_lock(&proc_viotape_mutex);
689 rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
690 mutex_unlock(&proc_viotape_mutex);
691 return rc;
692}
693
694static int viotap_open(struct inode *inode, struct file *file)
695{
696 HvLpEvent_Rc hvrc;
697 struct viot_devinfo_struct devi;
698 int ret;
699 struct op_struct *op = get_op_struct();
700
701 if (op == NULL)
702 return -ENOMEM;
703
704 mutex_lock(&proc_viotape_mutex);
705 get_dev_info(file->f_path.dentry->d_inode, &devi);
706
707 /* Note: We currently only support one mode! */
708 if ((devi.devno >= viotape_numdev) || (devi.mode)) {
709 ret = -ENODEV;
710 goto free_op;
711 }
712
713 init_completion(&op->com);
714
715 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
716 HvLpEvent_Type_VirtualIo,
717 viomajorsubtype_tape | viotapeopen,
718 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
719 viopath_sourceinst(viopath_hostLp),
720 viopath_targetinst(viopath_hostLp),
721 (u64)(unsigned long)op, VIOVERSION << 16,
722 ((u64)devi.devno << 48), 0, 0, 0);
723 if (hvrc != 0) {
724 printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
725 (int) hvrc);
726 ret = -EIO;
727 goto free_op;
728 }
729
730 wait_for_completion(&op->com);
731 ret = tape_rc_to_errno(op->rc, "open", devi.devno);
732
733free_op:
734 free_op_struct(op);
735 mutex_unlock(&proc_viotape_mutex);
736 return ret;
737}
738
739
740static int viotap_release(struct inode *inode, struct file *file)
741{
742 HvLpEvent_Rc hvrc;
743 struct viot_devinfo_struct devi;
744 int ret = 0;
745 struct op_struct *op = get_op_struct();
746
747 if (op == NULL)
748 return -ENOMEM;
749 init_completion(&op->com);
750
751 get_dev_info(file->f_path.dentry->d_inode, &devi);
752
753 if (devi.devno >= viotape_numdev) {
754 ret = -ENODEV;
755 goto free_op;
756 }
757
758 chg_state(devi.devno, VIOT_IDLE, file);
759
760 if (devi.rewind) {
761 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
762 HvLpEvent_Type_VirtualIo,
763 viomajorsubtype_tape | viotapeop,
764 HvLpEvent_AckInd_DoAck,
765 HvLpEvent_AckType_ImmediateAck,
766 viopath_sourceinst(viopath_hostLp),
767 viopath_targetinst(viopath_hostLp),
768 (u64)(unsigned long)op, VIOVERSION << 16,
769 ((u64)devi.devno << 48), 0,
770 ((u64)VIOTAPOP_REW) << 32, 0);
771 wait_for_completion(&op->com);
772
773 tape_rc_to_errno(op->rc, "rewind", devi.devno);
774 }
775
776 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
777 HvLpEvent_Type_VirtualIo,
778 viomajorsubtype_tape | viotapeclose,
779 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
780 viopath_sourceinst(viopath_hostLp),
781 viopath_targetinst(viopath_hostLp),
782 (u64)(unsigned long)op, VIOVERSION << 16,
783 ((u64)devi.devno << 48), 0, 0, 0);
784 if (hvrc != 0) {
785 printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
786 (int) hvrc);
787 ret = -EIO;
788 goto free_op;
789 }
790
791 wait_for_completion(&op->com);
792
793 if (op->rc)
794 printk(VIOTAPE_KERN_WARN "close failed\n");
795
796free_op:
797 free_op_struct(op);
798 return ret;
799}
800
801const struct file_operations viotap_fops = {
802 .owner = THIS_MODULE,
803 .read = viotap_read,
804 .write = viotap_write,
805 .unlocked_ioctl = viotap_unlocked_ioctl,
806 .open = viotap_open,
807 .release = viotap_release,
808 .llseek = noop_llseek,
809};
810
811/* Handle interrupt events for tape */
812static void vioHandleTapeEvent(struct HvLpEvent *event)
813{
814 int tapeminor;
815 struct op_struct *op;
816 struct viotapelpevent *tevent = (struct viotapelpevent *)event;
817
818 if (event == NULL) {
819 /* Notification that a partition went away! */
820 if (!viopath_isactive(viopath_hostLp)) {
821 /* TODO! Clean up */
822 }
823 return;
824 }
825
826 tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
827 op = (struct op_struct *)event->xCorrelationToken;
828 switch (tapeminor) {
829 case viotapeopen:
830 case viotapeclose:
831 op->rc = tevent->sub_type_result;
832 complete(&op->com);
833 break;
834 case viotaperead:
835 op->rc = tevent->sub_type_result;
836 op->count = tevent->len;
837 complete(&op->com);
838 break;
839 case viotapewrite:
840 if (op->non_blocking) {
841 dma_free_coherent(op->dev, op->count,
842 op->buffer, op->dmaaddr);
843 free_op_struct(op);
844 up(&reqSem);
845 } else {
846 op->rc = tevent->sub_type_result;
847 op->count = tevent->len;
848 complete(&op->com);
849 }
850 break;
851 case viotapeop:
852 case viotapegetpos:
853 case viotapesetpos:
854 case viotapegetstatus:
855 if (op) {
856 op->count = tevent->u.op.count;
857 op->rc = tevent->sub_type_result;
858 if (!op->non_blocking)
859 complete(&op->com);
860 }
861 break;
862 default:
863 printk(VIOTAPE_KERN_WARN "weird ack\n");
864 }
865}
866
867static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
868{
869 int i = vdev->unit_address;
870 int j;
871 struct device_node *node = vdev->dev.of_node;
872
873 if (i >= VIOTAPE_MAX_TAPE)
874 return -ENODEV;
875 if (!node)
876 return -ENODEV;
877
878 if (i >= viotape_numdev)
879 viotape_numdev = i + 1;
880
881 tape_device[i] = &vdev->dev;
882 viotape_unitinfo[i].rsrcname = of_get_property(node,
883 "linux,vio_rsrcname", NULL);
884 viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
885 NULL);
886 viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
887 NULL);
888
889 state[i].cur_part = 0;
890 for (j = 0; j < MAX_PARTITIONS; ++j)
891 state[i].part_stat_rwi[j] = VIOT_IDLE;
892 device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
893 "iseries!vt%d", i);
894 device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL,
895 "iseries!nvt%d", i);
896 printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
897 "resource %10.10s type %4.4s, model %3.3s\n",
898 i, viotape_unitinfo[i].rsrcname,
899 viotape_unitinfo[i].type, viotape_unitinfo[i].model);
900 return 0;
901}
902
903static int viotape_remove(struct vio_dev *vdev)
904{
905 int i = vdev->unit_address;
906
907 device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
908 device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
909 return 0;
910}
911
912/**
913 * viotape_device_table: Used by vio.c to match devices that we
914 * support.
915 */
916static struct vio_device_id viotape_device_table[] __devinitdata = {
917 { "byte", "IBM,iSeries-viotape" },
918 { "", "" }
919};
920MODULE_DEVICE_TABLE(vio, viotape_device_table);
921
922static struct vio_driver viotape_driver = {
923 .id_table = viotape_device_table,
924 .probe = viotape_probe,
925 .remove = viotape_remove,
926 .driver = {
927 .name = "viotape",
928 .owner = THIS_MODULE,
929 }
930};
931
932
933int __init viotap_init(void)
934{
935 int ret;
936
937 if (!firmware_has_feature(FW_FEATURE_ISERIES))
938 return -ENODEV;
939
940 op_struct_list = NULL;
941 if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) {
942 printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n");
943 return ret;
944 }
945 spin_lock_init(&op_struct_list_lock);
946
947 sema_init(&reqSem, VIOTAPE_MAXREQ);
948
949 if (viopath_hostLp == HvLpIndexInvalid) {
950 vio_set_hostlp();
951 if (viopath_hostLp == HvLpIndexInvalid) {
952 ret = -ENODEV;
953 goto clear_op;
954 }
955 }
956
957 ret = viopath_open(viopath_hostLp, viomajorsubtype_tape,
958 VIOTAPE_MAXREQ + 2);
959 if (ret) {
960 printk(VIOTAPE_KERN_WARN
961 "error on viopath_open to hostlp %d\n", ret);
962 ret = -EIO;
963 goto clear_op;
964 }
965
966 printk(VIOTAPE_KERN_INFO "vers " VIOTAPE_VERSION
967 ", hosting partition %d\n", viopath_hostLp);
968
969 vio_setHandler(viomajorsubtype_tape, vioHandleTapeEvent);
970
971 ret = register_chrdev(VIOTAPE_MAJOR, "viotape", &viotap_fops);
972 if (ret < 0) {
973 printk(VIOTAPE_KERN_WARN "Error registering viotape device\n");
974 goto clear_handler;
975 }
976
977 tape_class = class_create(THIS_MODULE, "tape");
978 if (IS_ERR(tape_class)) {
979 printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
980 ret = PTR_ERR(tape_class);
981 goto unreg_chrdev;
982 }
983
984 ret = vio_register_driver(&viotape_driver);
985 if (ret)
986 goto unreg_class;
987
988 proc_create("iSeries/viotape", S_IFREG|S_IRUGO, NULL,
989 &proc_viotape_operations);
990
991 return 0;
992
993unreg_class:
994 class_destroy(tape_class);
995unreg_chrdev:
996 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
997clear_handler:
998 vio_clearHandler(viomajorsubtype_tape);
999 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1000clear_op:
1001 clear_op_struct_pool();
1002 return ret;
1003}
1004
1005/* Give a new state to the tape object */
1006static int chg_state(int index, unsigned char new_state, struct file *file)
1007{
1008 unsigned char *cur_state =
1009 &state[index].part_stat_rwi[state[index].cur_part];
1010 int rc = 0;
1011
1012 /* if the same state, don't bother */
1013 if (*cur_state == new_state)
1014 return 0;
1015
1016 /* write an EOF if changing from writing to some other state */
1017 if (*cur_state == VIOT_WRITING) {
1018 struct mtop write_eof = { MTWEOF, 1 };
1019
1020 rc = viotap_ioctl(NULL, file, MTIOCTOP,
1021 (unsigned long)&write_eof);
1022 }
1023 *cur_state = new_state;
1024 return rc;
1025}
1026
1027/* Cleanup */
1028static void __exit viotap_exit(void)
1029{
1030 remove_proc_entry("iSeries/viotape", NULL);
1031 vio_unregister_driver(&viotape_driver);
1032 class_destroy(tape_class);
1033 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1034 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1035 vio_clearHandler(viomajorsubtype_tape);
1036 clear_op_struct_pool();
1037}
1038
1039MODULE_LICENSE("GPL");
1040module_init(viotap_init);
1041module_exit(viotap_exit);