blob: e4dda282e0a62a64ef6e15508e5da91417f6840d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 pt.c (c) 1998 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU General Public License.
4
5 This is the high-level driver for parallel port ATAPI tape
6 drives based on chips supported by the paride module.
7
8 The driver implements both rewinding and non-rewinding
9 devices, filemarks, and the rewind ioctl. It allocates
10 a small internal "bounce buffer" for each open device, but
11 otherwise expects buffering and blocking to be done at the
12 user level. As with most block-structured tapes, short
13 writes are padded to full tape blocks, so reading back a file
14 may return more data than was actually written.
15
16 By default, the driver will autoprobe for a single parallel
17 port ATAPI tape drive, but if their individual parameters are
18 specified, the driver can handle up to 4 drives.
19
20 The rewinding devices are named /dev/pt0, /dev/pt1, ...
21 while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
22
23 The behaviour of the pt driver can be altered by setting
24 some parameters from the insmod command line. The following
25 parameters are adjustable:
26
27 drive0 These four arguments can be arrays of
28 drive1 1-6 integers as follows:
29 drive2
30 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
31
32 Where,
33
34 <prt> is the base of the parallel port address for
35 the corresponding drive. (required)
36
37 <pro> is the protocol number for the adapter that
38 supports this drive. These numbers are
39 logged by 'paride' when the protocol modules
40 are initialised. (0 if not given)
41
42 <uni> for those adapters that support chained
43 devices, this is the unit selector for the
44 chain of devices on the given port. It should
45 be zero for devices that don't support chaining.
46 (0 if not given)
47
48 <mod> this can be -1 to choose the best mode, or one
49 of the mode numbers supported by the adapter.
50 (-1 if not given)
51
52 <slv> ATAPI devices can be jumpered to master or slave.
53 Set this to 0 to choose the master drive, 1 to
54 choose the slave, -1 (the default) to choose the
55 first drive found.
56
57 <dly> some parallel ports require the driver to
58 go more slowly. -1 sets a default value that
59 should work with the chosen protocol. Otherwise,
60 set this to a small integer, the larger it is
61 the slower the port i/o. In some cases, setting
62 this to zero will speed up the device. (default -1)
63
64 major You may use this parameter to overide the
65 default major number (96) that this driver
66 will use. Be sure to change the device
67 name as well.
68
69 name This parameter is a character string that
70 contains the name the kernel will use for this
71 device (in /proc output, for instance).
72 (default "pt").
73
74 verbose This parameter controls the amount of logging
75 that the driver will do. Set it to 0 for
76 normal operation, 1 to see autoprobe progress
77 messages, or 2 to see additional debugging
78 output. (default 0)
79
80 If this driver is built into the kernel, you can use
81 the following command line parameters, with the same values
82 as the corresponding module parameters listed above:
83
84 pt.drive0
85 pt.drive1
86 pt.drive2
87 pt.drive3
88
89 In addition, you can use the parameter pt.disable to disable
90 the driver entirely.
91
92*/
93
94/* Changes:
95
96 1.01 GRG 1998.05.06 Round up transfer size, fix ready_wait,
97 loosed interpretation of ATAPI standard
98 for clearing error status.
99 Eliminate sti();
100 1.02 GRG 1998.06.16 Eliminate an Ugh.
101 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing,
102 extra debugging
103 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support
104
105*/
106
107#define PT_VERSION "1.04"
108#define PT_MAJOR 96
109#define PT_NAME "pt"
110#define PT_UNITS 4
111
112/* Here are things one can override from the insmod command.
113 Most are autoprobed by paride unless set here. Verbose is on
114 by default.
115
116*/
117
118static int verbose = 0;
119static int major = PT_MAJOR;
120static char *name = PT_NAME;
121static int disable = 0;
122
123static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
124static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
125static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
126static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
127
128static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
129
130#define D_PRT 0
131#define D_PRO 1
132#define D_UNI 2
133#define D_MOD 3
134#define D_SLV 4
135#define D_DLY 5
136
137#define DU (*drives[unit])
138
139/* end of parameters */
140
141#include <linux/module.h>
142#include <linux/init.h>
143#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144#include <linux/delay.h>
145#include <linux/slab.h>
146#include <linux/mtio.h>
147#include <linux/device.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -0800148#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
Arnd Bergmann613655f2010-06-02 14:28:52 +0200149#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151#include <asm/uaccess.h>
152
153module_param(verbose, bool, 0);
154module_param(major, int, 0);
155module_param(name, charp, 0);
156module_param_array(drive0, int, NULL, 0);
157module_param_array(drive1, int, NULL, 0);
158module_param_array(drive2, int, NULL, 0);
159module_param_array(drive3, int, NULL, 0);
160
161#include "paride.h"
162
163#define PT_MAX_RETRIES 5
164#define PT_TMO 3000 /* interrupt timeout in jiffies */
165#define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
166#define PT_RESET_TMO 30 /* 30 seconds */
167#define PT_READY_TMO 60 /* 60 seconds */
168#define PT_REWIND_TMO 1200 /* 20 minutes */
169
170#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
171
172#define STAT_ERR 0x00001
173#define STAT_INDEX 0x00002
174#define STAT_ECC 0x00004
175#define STAT_DRQ 0x00008
176#define STAT_SEEK 0x00010
177#define STAT_WRERR 0x00020
178#define STAT_READY 0x00040
179#define STAT_BUSY 0x00080
180#define STAT_SENSE 0x1f000
181
182#define ATAPI_TEST_READY 0x00
183#define ATAPI_REWIND 0x01
184#define ATAPI_REQ_SENSE 0x03
185#define ATAPI_READ_6 0x08
186#define ATAPI_WRITE_6 0x0a
187#define ATAPI_WFM 0x10
188#define ATAPI_IDENTIFY 0x12
189#define ATAPI_MODE_SENSE 0x1a
190#define ATAPI_LOG_SENSE 0x4d
191
Arnd Bergmann613655f2010-06-02 14:28:52 +0200192static DEFINE_MUTEX(pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193static int pt_open(struct inode *inode, struct file *file);
Alan Coxbe1fd702008-07-04 09:51:21 +0200194static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195static int pt_release(struct inode *inode, struct file *file);
196static ssize_t pt_read(struct file *filp, char __user *buf,
197 size_t count, loff_t * ppos);
198static ssize_t pt_write(struct file *filp, const char __user *buf,
199 size_t count, loff_t * ppos);
200static int pt_detect(void);
201
202/* bits in tape->flags */
203
204#define PT_MEDIA 1
205#define PT_WRITE_OK 2
206#define PT_REWIND 4
207#define PT_WRITING 8
208#define PT_READING 16
209#define PT_EOF 32
210
211#define PT_NAMELEN 8
212#define PT_BUFSIZE 16384
213
214struct pt_unit {
215 struct pi_adapter pia; /* interface to paride layer */
216 struct pi_adapter *pi;
217 int flags; /* various state flags */
218 int last_sense; /* result of last request sense */
219 int drive; /* drive */
220 atomic_t available; /* 1 if access is available 0 otherwise */
221 int bs; /* block size */
222 int capacity; /* Size of tape in KB */
223 int present; /* device present ? */
224 char *bufptr;
225 char name[PT_NAMELEN]; /* pf0, pf1, ... */
226};
227
228static int pt_identify(struct pt_unit *tape);
229
230static struct pt_unit pt[PT_UNITS];
231
232static char pt_scratch[512]; /* scratch block buffer */
233
234/* kernel glue structures */
235
Arjan van de Ven2b8693c2007-02-12 00:55:32 -0800236static const struct file_operations pt_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 .owner = THIS_MODULE,
238 .read = pt_read,
239 .write = pt_write,
Alan Coxbe1fd702008-07-04 09:51:21 +0200240 .unlocked_ioctl = pt_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 .open = pt_open,
242 .release = pt_release,
243};
244
245/* sysfs class support */
gregkh@suse.dedeb36972005-03-23 09:52:10 -0800246static struct class *pt_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
248static inline int status_reg(struct pi_adapter *pi)
249{
250 return pi_read_regr(pi, 1, 6);
251}
252
253static inline int read_reg(struct pi_adapter *pi, int reg)
254{
255 return pi_read_regr(pi, 0, reg);
256}
257
258static inline void write_reg(struct pi_adapter *pi, int reg, int val)
259{
260 pi_write_regr(pi, 0, reg, val);
261}
262
263static inline u8 DRIVE(struct pt_unit *tape)
264{
265 return 0xa0+0x10*tape->drive;
266}
267
268static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg)
269{
270 int j, r, e, s, p;
271 struct pi_adapter *pi = tape->pi;
272
273 j = 0;
274 while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop))))
275 && (j++ < PT_SPIN))
276 udelay(PT_SPIN_DEL);
277
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800278 if ((r & (STAT_ERR & stop)) || (j > PT_SPIN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 s = read_reg(pi, 7);
280 e = read_reg(pi, 1);
281 p = read_reg(pi, 2);
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800282 if (j > PT_SPIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 e |= 0x100;
284 if (fun)
285 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
286 " loop=%d phase=%d\n",
287 tape->name, fun, msg, r, s, e, j, p);
288 return (e << 8) + s;
289 }
290 return 0;
291}
292
293static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun)
294{
295 struct pi_adapter *pi = tape->pi;
296 pi_connect(pi);
297
298 write_reg(pi, 6, DRIVE(tape));
299
300 if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
301 pi_disconnect(pi);
302 return -1;
303 }
304
305 write_reg(pi, 4, dlen % 256);
306 write_reg(pi, 5, dlen / 256);
307 write_reg(pi, 7, 0xa0); /* ATAPI packet command */
308
309 if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
310 pi_disconnect(pi);
311 return -1;
312 }
313
314 if (read_reg(pi, 2) != 1) {
315 printk("%s: %s: command phase error\n", tape->name, fun);
316 pi_disconnect(pi);
317 return -1;
318 }
319
320 pi_write_block(pi, cmd, 12);
321
322 return 0;
323}
324
325static int pt_completion(struct pt_unit *tape, char *buf, char *fun)
326{
327 struct pi_adapter *pi = tape->pi;
328 int r, s, n, p;
329
330 r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
331 fun, "completion");
332
333 if (read_reg(pi, 7) & STAT_DRQ) {
334 n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) +
335 3) & 0xfffc);
336 p = read_reg(pi, 2) & 3;
337 if (p == 0)
338 pi_write_block(pi, buf, n);
339 if (p == 2)
340 pi_read_block(pi, buf, n);
341 }
342
343 s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
344
345 pi_disconnect(pi);
346
347 return (r ? r : s);
348}
349
350static void pt_req_sense(struct pt_unit *tape, int quiet)
351{
352 char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
353 char buf[16];
354 int r;
355
356 r = pt_command(tape, rs_cmd, 16, "Request sense");
357 mdelay(1);
358 if (!r)
359 pt_completion(tape, buf, "Request sense");
360
361 tape->last_sense = -1;
362 if (!r) {
363 if (!quiet)
364 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
365 tape->name, buf[2] & 0xf, buf[12], buf[13]);
366 tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
367 | ((buf[13] & 0xff) << 16);
368 }
369}
370
371static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun)
372{
373 int r;
374
375 r = pt_command(tape, cmd, dlen, fun);
376 mdelay(1);
377 if (!r)
378 r = pt_completion(tape, buf, fun);
379 if (r)
380 pt_req_sense(tape, !fun);
381
382 return r;
383}
384
385static void pt_sleep(int cs)
386{
Nishanth Aravamudan86e84862005-09-10 00:27:28 -0700387 schedule_timeout_interruptible(cs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388}
389
390static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
391{
392 struct pi_adapter *pi = tape->pi;
393 int k, e, s;
394
395 k = 0;
396 e = 0;
397 s = 0;
398 while (k < tmo) {
399 pt_sleep(pause);
400 k++;
401 pi_connect(pi);
402 write_reg(pi, 6, DRIVE(tape));
403 s = read_reg(pi, 7);
404 e = read_reg(pi, 1);
405 pi_disconnect(pi);
406 if (s & (STAT_ERR | STAT_SEEK))
407 break;
408 }
409 if ((k >= tmo) || (s & STAT_ERR)) {
410 if (k >= tmo)
411 printk("%s: %s DSC timeout\n", tape->name, msg);
412 else
413 printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s,
414 e);
415 pt_req_sense(tape, 0);
416 return 0;
417 }
418 return 1;
419}
420
421static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun)
422{
423 if (pt_command(tape, cmd, 0, fun)) {
424 pt_req_sense(tape, 0);
425 return;
426 }
427 pi_disconnect(tape->pi);
428 pt_poll_dsc(tape, HZ, tmo, fun);
429}
430
431static void pt_rewind(struct pt_unit *tape)
432{
433 char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
434
435 pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind");
436}
437
438static void pt_write_fm(struct pt_unit *tape)
439{
440 char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
441
442 pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark");
443}
444
445#define DBMSG(msg) ((verbose>1)?(msg):NULL)
446
447static int pt_reset(struct pt_unit *tape)
448{
449 struct pi_adapter *pi = tape->pi;
450 int i, k, flg;
451 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
452
453 pi_connect(pi);
454 write_reg(pi, 6, DRIVE(tape));
455 write_reg(pi, 7, 8);
456
457 pt_sleep(20 * HZ / 1000);
458
459 k = 0;
460 while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY))
461 pt_sleep(HZ / 10);
462
463 flg = 1;
464 for (i = 0; i < 5; i++)
465 flg &= (read_reg(pi, i + 1) == expect[i]);
466
467 if (verbose) {
468 printk("%s: Reset (%d) signature = ", tape->name, k);
469 for (i = 0; i < 5; i++)
470 printk("%3x", read_reg(pi, i + 1));
471 if (!flg)
472 printk(" (incorrect)");
473 printk("\n");
474 }
475
476 pi_disconnect(pi);
477 return flg - 1;
478}
479
480static int pt_ready_wait(struct pt_unit *tape, int tmo)
481{
482 char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
483 int k, p;
484
485 k = 0;
486 while (k < tmo) {
487 tape->last_sense = 0;
488 pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready"));
489 p = tape->last_sense;
490 if (!p)
491 return 0;
492 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
493 return p;
494 k++;
495 pt_sleep(HZ);
496 }
497 return 0x000020; /* timeout */
498}
499
500static void xs(char *buf, char *targ, int offs, int len)
501{
502 int j, k, l;
503
504 j = 0;
505 l = 0;
506 for (k = 0; k < len; k++)
507 if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
508 l = targ[j++] = buf[k + offs];
509 if (l == 0x20)
510 j--;
511 targ[j] = 0;
512}
513
514static int xn(char *buf, int offs, int size)
515{
516 int v, k;
517
518 v = 0;
519 for (k = 0; k < size; k++)
520 v = v * 256 + (buf[k + offs] & 0xff);
521 return v;
522}
523
524static int pt_identify(struct pt_unit *tape)
525{
526 int dt, s;
527 char *ms[2] = { "master", "slave" };
528 char mf[10], id[18];
529 char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
530 char ms_cmd[12] =
531 { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
532 char ls_cmd[12] =
533 { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
534 char buf[36];
535
536 s = pt_atapi(tape, id_cmd, 36, buf, "identify");
537 if (s)
538 return -1;
539
540 dt = buf[0] & 0x1f;
541 if (dt != 1) {
542 if (verbose)
543 printk("%s: Drive %d, unsupported type %d\n",
544 tape->name, tape->drive, dt);
545 return -1;
546 }
547
548 xs(buf, mf, 8, 8);
549 xs(buf, id, 16, 16);
550
551 tape->flags = 0;
552 tape->capacity = 0;
553 tape->bs = 0;
554
555 if (!pt_ready_wait(tape, PT_READY_TMO))
556 tape->flags |= PT_MEDIA;
557
558 if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) {
559 if (!(buf[2] & 0x80))
560 tape->flags |= PT_WRITE_OK;
561 tape->bs = xn(buf, 10, 2);
562 }
563
564 if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense"))
565 tape->capacity = xn(buf, 24, 4);
566
567 printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]);
568 if (!(tape->flags & PT_MEDIA))
569 printk(", no media\n");
570 else {
571 if (!(tape->flags & PT_WRITE_OK))
572 printk(", RO");
573 printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024);
574 }
575
576 return 0;
577}
578
579
580/*
581 * returns 0, with id set if drive is detected
582 * -1, if drive detection failed
583 */
584static int pt_probe(struct pt_unit *tape)
585{
586 if (tape->drive == -1) {
587 for (tape->drive = 0; tape->drive <= 1; tape->drive++)
588 if (!pt_reset(tape))
589 return pt_identify(tape);
590 } else {
591 if (!pt_reset(tape))
592 return pt_identify(tape);
593 }
594 return -1;
595}
596
597static int pt_detect(void)
598{
599 struct pt_unit *tape;
600 int specified = 0, found = 0;
601 int unit;
602
603 printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
604
605 specified = 0;
606 for (unit = 0; unit < PT_UNITS; unit++) {
607 struct pt_unit *tape = &pt[unit];
608 tape->pi = &tape->pia;
609 atomic_set(&tape->available, 1);
610 tape->flags = 0;
611 tape->last_sense = 0;
612 tape->present = 0;
613 tape->bufptr = NULL;
614 tape->drive = DU[D_SLV];
615 snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit);
616 if (!DU[D_PRT])
617 continue;
618 specified++;
619 if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],
620 DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,
621 verbose, tape->name)) {
622 if (!pt_probe(tape)) {
623 tape->present = 1;
624 found++;
625 } else
626 pi_release(tape->pi);
627 }
628 }
629 if (specified == 0) {
630 tape = pt;
631 if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch,
632 PI_PT, verbose, tape->name)) {
633 if (!pt_probe(tape)) {
634 tape->present = 1;
635 found++;
636 } else
637 pi_release(tape->pi);
638 }
639
640 }
641 if (found)
642 return 0;
643
644 printk("%s: No ATAPI tape drive detected\n", name);
645 return -1;
646}
647
648static int pt_open(struct inode *inode, struct file *file)
649{
650 int unit = iminor(inode) & 0x7F;
651 struct pt_unit *tape = pt + unit;
652 int err;
653
Arnd Bergmann613655f2010-06-02 14:28:52 +0200654 mutex_lock(&pt_mutex);
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600655 if (unit >= PT_UNITS || (!tape->present)) {
Arnd Bergmann613655f2010-06-02 14:28:52 +0200656 mutex_unlock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 return -ENODEV;
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 err = -EBUSY;
661 if (!atomic_dec_and_test(&tape->available))
662 goto out;
663
664 pt_identify(tape);
665
666 err = -ENODEV;
Alexey Dobriyaneaa0ff12008-02-06 01:36:06 -0800667 if (!(tape->flags & PT_MEDIA))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 goto out;
669
670 err = -EROFS;
Al Viroaeb5d722008-09-02 15:28:45 -0400671 if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & FMODE_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 goto out;
673
674 if (!(iminor(inode) & 128))
675 tape->flags |= PT_REWIND;
676
677 err = -ENOMEM;
678 tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
679 if (tape->bufptr == NULL) {
680 printk("%s: buffer allocation failed\n", tape->name);
681 goto out;
682 }
683
684 file->private_data = tape;
Arnd Bergmann613655f2010-06-02 14:28:52 +0200685 mutex_unlock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return 0;
687
688out:
689 atomic_inc(&tape->available);
Arnd Bergmann613655f2010-06-02 14:28:52 +0200690 mutex_unlock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 return err;
692}
693
Alan Coxbe1fd702008-07-04 09:51:21 +0200694static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
696 struct pt_unit *tape = file->private_data;
697 struct mtop __user *p = (void __user *)arg;
698 struct mtop mtop;
699
700 switch (cmd) {
701 case MTIOCTOP:
702 if (copy_from_user(&mtop, p, sizeof(struct mtop)))
703 return -EFAULT;
704
705 switch (mtop.mt_op) {
706
707 case MTREW:
Arnd Bergmann613655f2010-06-02 14:28:52 +0200708 mutex_lock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 pt_rewind(tape);
Arnd Bergmann613655f2010-06-02 14:28:52 +0200710 mutex_unlock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 return 0;
712
713 case MTWEOF:
Arnd Bergmann613655f2010-06-02 14:28:52 +0200714 mutex_lock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 pt_write_fm(tape);
Arnd Bergmann613655f2010-06-02 14:28:52 +0200716 mutex_unlock(&pt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 return 0;
718
719 default:
Alan Coxbe1fd702008-07-04 09:51:21 +0200720 /* FIXME: rate limit ?? */
721 printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 mtop.mt_op);
723 return -EINVAL;
724 }
725
726 default:
Alan Coxbe1fd702008-07-04 09:51:21 +0200727 return -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 }
729}
730
731static int
732pt_release(struct inode *inode, struct file *file)
733{
734 struct pt_unit *tape = file->private_data;
735
736 if (atomic_read(&tape->available) > 1)
737 return -EINVAL;
738
739 if (tape->flags & PT_WRITING)
740 pt_write_fm(tape);
741
742 if (tape->flags & PT_REWIND)
743 pt_rewind(tape);
744
745 kfree(tape->bufptr);
746 tape->bufptr = NULL;
747
748 atomic_inc(&tape->available);
749
750 return 0;
751
752}
753
754static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
755{
756 struct pt_unit *tape = filp->private_data;
757 struct pi_adapter *pi = tape->pi;
758 char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
759 int k, n, r, p, s, t, b;
760
761 if (!(tape->flags & (PT_READING | PT_WRITING))) {
762 tape->flags |= PT_READING;
763 if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))
764 return -EIO;
765 } else if (tape->flags & PT_WRITING)
766 return -EIO;
767
768 if (tape->flags & PT_EOF)
769 return 0;
770
771 t = 0;
772
773 while (count > 0) {
774
775 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))
776 return -EIO;
777
778 n = count;
779 if (n > 32768)
780 n = 32768; /* max per command */
781 b = (n - 1 + tape->bs) / tape->bs;
782 n = b * tape->bs; /* rounded up to even block */
783
784 rd_cmd[4] = b;
785
786 r = pt_command(tape, rd_cmd, n, "read");
787
788 mdelay(1);
789
790 if (r) {
791 pt_req_sense(tape, 0);
792 return -EIO;
793 }
794
795 while (1) {
796
797 r = pt_wait(tape, STAT_BUSY,
798 STAT_DRQ | STAT_ERR | STAT_READY,
799 DBMSG("read DRQ"), "");
800
801 if (r & STAT_SENSE) {
802 pi_disconnect(pi);
803 pt_req_sense(tape, 0);
804 return -EIO;
805 }
806
807 if (r)
808 tape->flags |= PT_EOF;
809
810 s = read_reg(pi, 7);
811
812 if (!(s & STAT_DRQ))
813 break;
814
815 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
816 p = (read_reg(pi, 2) & 3);
817 if (p != 2) {
818 pi_disconnect(pi);
819 printk("%s: Phase error on read: %d\n", tape->name,
820 p);
821 return -EIO;
822 }
823
824 while (n > 0) {
825 k = n;
826 if (k > PT_BUFSIZE)
827 k = PT_BUFSIZE;
828 pi_read_block(pi, tape->bufptr, k);
829 n -= k;
830 b = k;
831 if (b > count)
832 b = count;
833 if (copy_to_user(buf + t, tape->bufptr, b)) {
834 pi_disconnect(pi);
835 return -EFAULT;
836 }
837 t += b;
838 count -= b;
839 }
840
841 }
842 pi_disconnect(pi);
843 if (tape->flags & PT_EOF)
844 break;
845 }
846
847 return t;
848
849}
850
851static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
852{
853 struct pt_unit *tape = filp->private_data;
854 struct pi_adapter *pi = tape->pi;
855 char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
856 int k, n, r, p, s, t, b;
857
858 if (!(tape->flags & PT_WRITE_OK))
859 return -EROFS;
860
861 if (!(tape->flags & (PT_READING | PT_WRITING))) {
862 tape->flags |= PT_WRITING;
863 if (pt_atapi
864 (tape, wr_cmd, 0, NULL, "start buffer-available mode"))
865 return -EIO;
866 } else if (tape->flags & PT_READING)
867 return -EIO;
868
869 if (tape->flags & PT_EOF)
870 return -ENOSPC;
871
872 t = 0;
873
874 while (count > 0) {
875
876 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))
877 return -EIO;
878
879 n = count;
880 if (n > 32768)
881 n = 32768; /* max per command */
882 b = (n - 1 + tape->bs) / tape->bs;
883 n = b * tape->bs; /* rounded up to even block */
884
885 wr_cmd[4] = b;
886
887 r = pt_command(tape, wr_cmd, n, "write");
888
889 mdelay(1);
890
891 if (r) { /* error delivering command only */
892 pt_req_sense(tape, 0);
893 return -EIO;
894 }
895
896 while (1) {
897
898 r = pt_wait(tape, STAT_BUSY,
899 STAT_DRQ | STAT_ERR | STAT_READY,
900 DBMSG("write DRQ"), NULL);
901
902 if (r & STAT_SENSE) {
903 pi_disconnect(pi);
904 pt_req_sense(tape, 0);
905 return -EIO;
906 }
907
908 if (r)
909 tape->flags |= PT_EOF;
910
911 s = read_reg(pi, 7);
912
913 if (!(s & STAT_DRQ))
914 break;
915
916 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
917 p = (read_reg(pi, 2) & 3);
918 if (p != 0) {
919 pi_disconnect(pi);
920 printk("%s: Phase error on write: %d \n",
921 tape->name, p);
922 return -EIO;
923 }
924
925 while (n > 0) {
926 k = n;
927 if (k > PT_BUFSIZE)
928 k = PT_BUFSIZE;
929 b = k;
930 if (b > count)
931 b = count;
932 if (copy_from_user(tape->bufptr, buf + t, b)) {
933 pi_disconnect(pi);
934 return -EFAULT;
935 }
936 pi_write_block(pi, tape->bufptr, k);
937 t += b;
938 count -= b;
939 n -= k;
940 }
941
942 }
943 pi_disconnect(pi);
944 if (tape->flags & PT_EOF)
945 break;
946 }
947
948 return t;
949}
950
951static int __init pt_init(void)
952{
Andrew Morton829d5f62006-03-28 01:56:18 -0800953 int unit;
954 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 if (disable) {
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800957 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 goto out;
959 }
960
961 if (pt_detect()) {
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800962 err = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 goto out;
964 }
965
Andrew Morton829d5f62006-03-28 01:56:18 -0800966 err = register_chrdev(major, name, &pt_fops);
967 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 printk("pt_init: unable to get major number %d\n", major);
969 for (unit = 0; unit < PT_UNITS; unit++)
970 if (pt[unit].present)
971 pi_release(pt[unit].pi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 goto out;
973 }
Andrew Morton829d5f62006-03-28 01:56:18 -0800974 major = err;
gregkh@suse.dedeb36972005-03-23 09:52:10 -0800975 pt_class = class_create(THIS_MODULE, "pt");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 if (IS_ERR(pt_class)) {
977 err = PTR_ERR(pt_class);
978 goto out_chrdev;
979 }
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 for (unit = 0; unit < PT_UNITS; unit++)
982 if (pt[unit].present) {
Greg Kroah-Hartman1ff9f542008-07-21 20:03:34 -0700983 device_create(pt_class, NULL, MKDEV(major, unit), NULL,
984 "pt%d", unit);
985 device_create(pt_class, NULL, MKDEV(major, unit + 128),
986 NULL, "pt%dn", unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988 goto out;
989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990out_chrdev:
991 unregister_chrdev(major, "pt");
992out:
993 return err;
994}
995
996static void __exit pt_exit(void)
997{
998 int unit;
999 for (unit = 0; unit < PT_UNITS; unit++)
1000 if (pt[unit].present) {
Tony Jonesaa275822007-09-25 02:03:03 +02001001 device_destroy(pt_class, MKDEV(major, unit));
1002 device_destroy(pt_class, MKDEV(major, unit + 128));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
gregkh@suse.dedeb36972005-03-23 09:52:10 -08001004 class_destroy(pt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 unregister_chrdev(major, name);
1006 for (unit = 0; unit < PT_UNITS; unit++)
1007 if (pt[unit].present)
1008 pi_release(pt[unit].pi);
1009}
1010
1011MODULE_LICENSE("GPL");
1012module_init(pt_init)
1013module_exit(pt_exit)