blob: 673b8b2fd337a1e22b442eba939aa4c90a407b86 [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() */
Alan Coxbe1fd702008-07-04 09:51:21 +0200149#include <linux/smp_lock.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
192static int pt_open(struct inode *inode, struct file *file);
Alan Coxbe1fd702008-07-04 09:51:21 +0200193static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static int pt_release(struct inode *inode, struct file *file);
195static ssize_t pt_read(struct file *filp, char __user *buf,
196 size_t count, loff_t * ppos);
197static ssize_t pt_write(struct file *filp, const char __user *buf,
198 size_t count, loff_t * ppos);
199static int pt_detect(void);
200
201/* bits in tape->flags */
202
203#define PT_MEDIA 1
204#define PT_WRITE_OK 2
205#define PT_REWIND 4
206#define PT_WRITING 8
207#define PT_READING 16
208#define PT_EOF 32
209
210#define PT_NAMELEN 8
211#define PT_BUFSIZE 16384
212
213struct pt_unit {
214 struct pi_adapter pia; /* interface to paride layer */
215 struct pi_adapter *pi;
216 int flags; /* various state flags */
217 int last_sense; /* result of last request sense */
218 int drive; /* drive */
219 atomic_t available; /* 1 if access is available 0 otherwise */
220 int bs; /* block size */
221 int capacity; /* Size of tape in KB */
222 int present; /* device present ? */
223 char *bufptr;
224 char name[PT_NAMELEN]; /* pf0, pf1, ... */
225};
226
227static int pt_identify(struct pt_unit *tape);
228
229static struct pt_unit pt[PT_UNITS];
230
231static char pt_scratch[512]; /* scratch block buffer */
232
233/* kernel glue structures */
234
Arjan van de Ven2b8693c2007-02-12 00:55:32 -0800235static const struct file_operations pt_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 .owner = THIS_MODULE,
237 .read = pt_read,
238 .write = pt_write,
Alan Coxbe1fd702008-07-04 09:51:21 +0200239 .unlocked_ioctl = pt_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 .open = pt_open,
241 .release = pt_release,
242};
243
244/* sysfs class support */
gregkh@suse.dedeb36972005-03-23 09:52:10 -0800245static struct class *pt_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
247static inline int status_reg(struct pi_adapter *pi)
248{
249 return pi_read_regr(pi, 1, 6);
250}
251
252static inline int read_reg(struct pi_adapter *pi, int reg)
253{
254 return pi_read_regr(pi, 0, reg);
255}
256
257static inline void write_reg(struct pi_adapter *pi, int reg, int val)
258{
259 pi_write_regr(pi, 0, reg, val);
260}
261
262static inline u8 DRIVE(struct pt_unit *tape)
263{
264 return 0xa0+0x10*tape->drive;
265}
266
267static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg)
268{
269 int j, r, e, s, p;
270 struct pi_adapter *pi = tape->pi;
271
272 j = 0;
273 while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop))))
274 && (j++ < PT_SPIN))
275 udelay(PT_SPIN_DEL);
276
277 if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) {
278 s = read_reg(pi, 7);
279 e = read_reg(pi, 1);
280 p = read_reg(pi, 2);
281 if (j >= PT_SPIN)
282 e |= 0x100;
283 if (fun)
284 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
285 " loop=%d phase=%d\n",
286 tape->name, fun, msg, r, s, e, j, p);
287 return (e << 8) + s;
288 }
289 return 0;
290}
291
292static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun)
293{
294 struct pi_adapter *pi = tape->pi;
295 pi_connect(pi);
296
297 write_reg(pi, 6, DRIVE(tape));
298
299 if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
300 pi_disconnect(pi);
301 return -1;
302 }
303
304 write_reg(pi, 4, dlen % 256);
305 write_reg(pi, 5, dlen / 256);
306 write_reg(pi, 7, 0xa0); /* ATAPI packet command */
307
308 if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
309 pi_disconnect(pi);
310 return -1;
311 }
312
313 if (read_reg(pi, 2) != 1) {
314 printk("%s: %s: command phase error\n", tape->name, fun);
315 pi_disconnect(pi);
316 return -1;
317 }
318
319 pi_write_block(pi, cmd, 12);
320
321 return 0;
322}
323
324static int pt_completion(struct pt_unit *tape, char *buf, char *fun)
325{
326 struct pi_adapter *pi = tape->pi;
327 int r, s, n, p;
328
329 r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
330 fun, "completion");
331
332 if (read_reg(pi, 7) & STAT_DRQ) {
333 n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) +
334 3) & 0xfffc);
335 p = read_reg(pi, 2) & 3;
336 if (p == 0)
337 pi_write_block(pi, buf, n);
338 if (p == 2)
339 pi_read_block(pi, buf, n);
340 }
341
342 s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
343
344 pi_disconnect(pi);
345
346 return (r ? r : s);
347}
348
349static void pt_req_sense(struct pt_unit *tape, int quiet)
350{
351 char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
352 char buf[16];
353 int r;
354
355 r = pt_command(tape, rs_cmd, 16, "Request sense");
356 mdelay(1);
357 if (!r)
358 pt_completion(tape, buf, "Request sense");
359
360 tape->last_sense = -1;
361 if (!r) {
362 if (!quiet)
363 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
364 tape->name, buf[2] & 0xf, buf[12], buf[13]);
365 tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
366 | ((buf[13] & 0xff) << 16);
367 }
368}
369
370static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun)
371{
372 int r;
373
374 r = pt_command(tape, cmd, dlen, fun);
375 mdelay(1);
376 if (!r)
377 r = pt_completion(tape, buf, fun);
378 if (r)
379 pt_req_sense(tape, !fun);
380
381 return r;
382}
383
384static void pt_sleep(int cs)
385{
Nishanth Aravamudan86e84862005-09-10 00:27:28 -0700386 schedule_timeout_interruptible(cs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387}
388
389static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
390{
391 struct pi_adapter *pi = tape->pi;
392 int k, e, s;
393
394 k = 0;
395 e = 0;
396 s = 0;
397 while (k < tmo) {
398 pt_sleep(pause);
399 k++;
400 pi_connect(pi);
401 write_reg(pi, 6, DRIVE(tape));
402 s = read_reg(pi, 7);
403 e = read_reg(pi, 1);
404 pi_disconnect(pi);
405 if (s & (STAT_ERR | STAT_SEEK))
406 break;
407 }
408 if ((k >= tmo) || (s & STAT_ERR)) {
409 if (k >= tmo)
410 printk("%s: %s DSC timeout\n", tape->name, msg);
411 else
412 printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s,
413 e);
414 pt_req_sense(tape, 0);
415 return 0;
416 }
417 return 1;
418}
419
420static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun)
421{
422 if (pt_command(tape, cmd, 0, fun)) {
423 pt_req_sense(tape, 0);
424 return;
425 }
426 pi_disconnect(tape->pi);
427 pt_poll_dsc(tape, HZ, tmo, fun);
428}
429
430static void pt_rewind(struct pt_unit *tape)
431{
432 char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
433
434 pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind");
435}
436
437static void pt_write_fm(struct pt_unit *tape)
438{
439 char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
440
441 pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark");
442}
443
444#define DBMSG(msg) ((verbose>1)?(msg):NULL)
445
446static int pt_reset(struct pt_unit *tape)
447{
448 struct pi_adapter *pi = tape->pi;
449 int i, k, flg;
450 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
451
452 pi_connect(pi);
453 write_reg(pi, 6, DRIVE(tape));
454 write_reg(pi, 7, 8);
455
456 pt_sleep(20 * HZ / 1000);
457
458 k = 0;
459 while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY))
460 pt_sleep(HZ / 10);
461
462 flg = 1;
463 for (i = 0; i < 5; i++)
464 flg &= (read_reg(pi, i + 1) == expect[i]);
465
466 if (verbose) {
467 printk("%s: Reset (%d) signature = ", tape->name, k);
468 for (i = 0; i < 5; i++)
469 printk("%3x", read_reg(pi, i + 1));
470 if (!flg)
471 printk(" (incorrect)");
472 printk("\n");
473 }
474
475 pi_disconnect(pi);
476 return flg - 1;
477}
478
479static int pt_ready_wait(struct pt_unit *tape, int tmo)
480{
481 char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
482 int k, p;
483
484 k = 0;
485 while (k < tmo) {
486 tape->last_sense = 0;
487 pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready"));
488 p = tape->last_sense;
489 if (!p)
490 return 0;
491 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
492 return p;
493 k++;
494 pt_sleep(HZ);
495 }
496 return 0x000020; /* timeout */
497}
498
499static void xs(char *buf, char *targ, int offs, int len)
500{
501 int j, k, l;
502
503 j = 0;
504 l = 0;
505 for (k = 0; k < len; k++)
506 if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
507 l = targ[j++] = buf[k + offs];
508 if (l == 0x20)
509 j--;
510 targ[j] = 0;
511}
512
513static int xn(char *buf, int offs, int size)
514{
515 int v, k;
516
517 v = 0;
518 for (k = 0; k < size; k++)
519 v = v * 256 + (buf[k + offs] & 0xff);
520 return v;
521}
522
523static int pt_identify(struct pt_unit *tape)
524{
525 int dt, s;
526 char *ms[2] = { "master", "slave" };
527 char mf[10], id[18];
528 char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
529 char ms_cmd[12] =
530 { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
531 char ls_cmd[12] =
532 { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
533 char buf[36];
534
535 s = pt_atapi(tape, id_cmd, 36, buf, "identify");
536 if (s)
537 return -1;
538
539 dt = buf[0] & 0x1f;
540 if (dt != 1) {
541 if (verbose)
542 printk("%s: Drive %d, unsupported type %d\n",
543 tape->name, tape->drive, dt);
544 return -1;
545 }
546
547 xs(buf, mf, 8, 8);
548 xs(buf, id, 16, 16);
549
550 tape->flags = 0;
551 tape->capacity = 0;
552 tape->bs = 0;
553
554 if (!pt_ready_wait(tape, PT_READY_TMO))
555 tape->flags |= PT_MEDIA;
556
557 if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) {
558 if (!(buf[2] & 0x80))
559 tape->flags |= PT_WRITE_OK;
560 tape->bs = xn(buf, 10, 2);
561 }
562
563 if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense"))
564 tape->capacity = xn(buf, 24, 4);
565
566 printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]);
567 if (!(tape->flags & PT_MEDIA))
568 printk(", no media\n");
569 else {
570 if (!(tape->flags & PT_WRITE_OK))
571 printk(", RO");
572 printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024);
573 }
574
575 return 0;
576}
577
578
579/*
580 * returns 0, with id set if drive is detected
581 * -1, if drive detection failed
582 */
583static int pt_probe(struct pt_unit *tape)
584{
585 if (tape->drive == -1) {
586 for (tape->drive = 0; tape->drive <= 1; tape->drive++)
587 if (!pt_reset(tape))
588 return pt_identify(tape);
589 } else {
590 if (!pt_reset(tape))
591 return pt_identify(tape);
592 }
593 return -1;
594}
595
596static int pt_detect(void)
597{
598 struct pt_unit *tape;
599 int specified = 0, found = 0;
600 int unit;
601
602 printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
603
604 specified = 0;
605 for (unit = 0; unit < PT_UNITS; unit++) {
606 struct pt_unit *tape = &pt[unit];
607 tape->pi = &tape->pia;
608 atomic_set(&tape->available, 1);
609 tape->flags = 0;
610 tape->last_sense = 0;
611 tape->present = 0;
612 tape->bufptr = NULL;
613 tape->drive = DU[D_SLV];
614 snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit);
615 if (!DU[D_PRT])
616 continue;
617 specified++;
618 if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],
619 DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,
620 verbose, tape->name)) {
621 if (!pt_probe(tape)) {
622 tape->present = 1;
623 found++;
624 } else
625 pi_release(tape->pi);
626 }
627 }
628 if (specified == 0) {
629 tape = pt;
630 if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch,
631 PI_PT, verbose, tape->name)) {
632 if (!pt_probe(tape)) {
633 tape->present = 1;
634 found++;
635 } else
636 pi_release(tape->pi);
637 }
638
639 }
640 if (found)
641 return 0;
642
643 printk("%s: No ATAPI tape drive detected\n", name);
644 return -1;
645}
646
647static int pt_open(struct inode *inode, struct file *file)
648{
649 int unit = iminor(inode) & 0x7F;
650 struct pt_unit *tape = pt + unit;
651 int err;
652
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600653 lock_kernel();
654 if (unit >= PT_UNITS || (!tape->present)) {
655 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return -ENODEV;
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 err = -EBUSY;
660 if (!atomic_dec_and_test(&tape->available))
661 goto out;
662
663 pt_identify(tape);
664
665 err = -ENODEV;
Alexey Dobriyaneaa0ff12008-02-06 01:36:06 -0800666 if (!(tape->flags & PT_MEDIA))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 goto out;
668
669 err = -EROFS;
Roel Kluinb07989f2007-11-05 14:50:58 -0800670 if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 goto out;
672
673 if (!(iminor(inode) & 128))
674 tape->flags |= PT_REWIND;
675
676 err = -ENOMEM;
677 tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
678 if (tape->bufptr == NULL) {
679 printk("%s: buffer allocation failed\n", tape->name);
680 goto out;
681 }
682
683 file->private_data = tape;
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600684 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 return 0;
686
687out:
688 atomic_inc(&tape->available);
Jonathan Corbetea2959a2008-05-15 10:07:56 -0600689 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return err;
691}
692
Alan Coxbe1fd702008-07-04 09:51:21 +0200693static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
695 struct pt_unit *tape = file->private_data;
696 struct mtop __user *p = (void __user *)arg;
697 struct mtop mtop;
698
699 switch (cmd) {
700 case MTIOCTOP:
701 if (copy_from_user(&mtop, p, sizeof(struct mtop)))
702 return -EFAULT;
703
704 switch (mtop.mt_op) {
705
706 case MTREW:
Alan Coxbe1fd702008-07-04 09:51:21 +0200707 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 pt_rewind(tape);
Alan Coxbe1fd702008-07-04 09:51:21 +0200709 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return 0;
711
712 case MTWEOF:
Alan Coxbe1fd702008-07-04 09:51:21 +0200713 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 pt_write_fm(tape);
Alan Coxbe1fd702008-07-04 09:51:21 +0200715 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return 0;
717
718 default:
Alan Coxbe1fd702008-07-04 09:51:21 +0200719 /* FIXME: rate limit ?? */
720 printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 mtop.mt_op);
722 return -EINVAL;
723 }
724
725 default:
Alan Coxbe1fd702008-07-04 09:51:21 +0200726 return -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
728}
729
730static int
731pt_release(struct inode *inode, struct file *file)
732{
733 struct pt_unit *tape = file->private_data;
734
735 if (atomic_read(&tape->available) > 1)
736 return -EINVAL;
737
738 if (tape->flags & PT_WRITING)
739 pt_write_fm(tape);
740
741 if (tape->flags & PT_REWIND)
742 pt_rewind(tape);
743
744 kfree(tape->bufptr);
745 tape->bufptr = NULL;
746
747 atomic_inc(&tape->available);
748
749 return 0;
750
751}
752
753static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
754{
755 struct pt_unit *tape = filp->private_data;
756 struct pi_adapter *pi = tape->pi;
757 char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
758 int k, n, r, p, s, t, b;
759
760 if (!(tape->flags & (PT_READING | PT_WRITING))) {
761 tape->flags |= PT_READING;
762 if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))
763 return -EIO;
764 } else if (tape->flags & PT_WRITING)
765 return -EIO;
766
767 if (tape->flags & PT_EOF)
768 return 0;
769
770 t = 0;
771
772 while (count > 0) {
773
774 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))
775 return -EIO;
776
777 n = count;
778 if (n > 32768)
779 n = 32768; /* max per command */
780 b = (n - 1 + tape->bs) / tape->bs;
781 n = b * tape->bs; /* rounded up to even block */
782
783 rd_cmd[4] = b;
784
785 r = pt_command(tape, rd_cmd, n, "read");
786
787 mdelay(1);
788
789 if (r) {
790 pt_req_sense(tape, 0);
791 return -EIO;
792 }
793
794 while (1) {
795
796 r = pt_wait(tape, STAT_BUSY,
797 STAT_DRQ | STAT_ERR | STAT_READY,
798 DBMSG("read DRQ"), "");
799
800 if (r & STAT_SENSE) {
801 pi_disconnect(pi);
802 pt_req_sense(tape, 0);
803 return -EIO;
804 }
805
806 if (r)
807 tape->flags |= PT_EOF;
808
809 s = read_reg(pi, 7);
810
811 if (!(s & STAT_DRQ))
812 break;
813
814 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
815 p = (read_reg(pi, 2) & 3);
816 if (p != 2) {
817 pi_disconnect(pi);
818 printk("%s: Phase error on read: %d\n", tape->name,
819 p);
820 return -EIO;
821 }
822
823 while (n > 0) {
824 k = n;
825 if (k > PT_BUFSIZE)
826 k = PT_BUFSIZE;
827 pi_read_block(pi, tape->bufptr, k);
828 n -= k;
829 b = k;
830 if (b > count)
831 b = count;
832 if (copy_to_user(buf + t, tape->bufptr, b)) {
833 pi_disconnect(pi);
834 return -EFAULT;
835 }
836 t += b;
837 count -= b;
838 }
839
840 }
841 pi_disconnect(pi);
842 if (tape->flags & PT_EOF)
843 break;
844 }
845
846 return t;
847
848}
849
850static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
851{
852 struct pt_unit *tape = filp->private_data;
853 struct pi_adapter *pi = tape->pi;
854 char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
855 int k, n, r, p, s, t, b;
856
857 if (!(tape->flags & PT_WRITE_OK))
858 return -EROFS;
859
860 if (!(tape->flags & (PT_READING | PT_WRITING))) {
861 tape->flags |= PT_WRITING;
862 if (pt_atapi
863 (tape, wr_cmd, 0, NULL, "start buffer-available mode"))
864 return -EIO;
865 } else if (tape->flags & PT_READING)
866 return -EIO;
867
868 if (tape->flags & PT_EOF)
869 return -ENOSPC;
870
871 t = 0;
872
873 while (count > 0) {
874
875 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))
876 return -EIO;
877
878 n = count;
879 if (n > 32768)
880 n = 32768; /* max per command */
881 b = (n - 1 + tape->bs) / tape->bs;
882 n = b * tape->bs; /* rounded up to even block */
883
884 wr_cmd[4] = b;
885
886 r = pt_command(tape, wr_cmd, n, "write");
887
888 mdelay(1);
889
890 if (r) { /* error delivering command only */
891 pt_req_sense(tape, 0);
892 return -EIO;
893 }
894
895 while (1) {
896
897 r = pt_wait(tape, STAT_BUSY,
898 STAT_DRQ | STAT_ERR | STAT_READY,
899 DBMSG("write DRQ"), NULL);
900
901 if (r & STAT_SENSE) {
902 pi_disconnect(pi);
903 pt_req_sense(tape, 0);
904 return -EIO;
905 }
906
907 if (r)
908 tape->flags |= PT_EOF;
909
910 s = read_reg(pi, 7);
911
912 if (!(s & STAT_DRQ))
913 break;
914
915 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
916 p = (read_reg(pi, 2) & 3);
917 if (p != 0) {
918 pi_disconnect(pi);
919 printk("%s: Phase error on write: %d \n",
920 tape->name, p);
921 return -EIO;
922 }
923
924 while (n > 0) {
925 k = n;
926 if (k > PT_BUFSIZE)
927 k = PT_BUFSIZE;
928 b = k;
929 if (b > count)
930 b = count;
931 if (copy_from_user(tape->bufptr, buf + t, b)) {
932 pi_disconnect(pi);
933 return -EFAULT;
934 }
935 pi_write_block(pi, tape->bufptr, k);
936 t += b;
937 count -= b;
938 n -= k;
939 }
940
941 }
942 pi_disconnect(pi);
943 if (tape->flags & PT_EOF)
944 break;
945 }
946
947 return t;
948}
949
950static int __init pt_init(void)
951{
Andrew Morton829d5f62006-03-28 01:56:18 -0800952 int unit;
953 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955 if (disable) {
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800956 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 goto out;
958 }
959
960 if (pt_detect()) {
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800961 err = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 goto out;
963 }
964
Andrew Morton829d5f62006-03-28 01:56:18 -0800965 err = register_chrdev(major, name, &pt_fops);
966 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 printk("pt_init: unable to get major number %d\n", major);
968 for (unit = 0; unit < PT_UNITS; unit++)
969 if (pt[unit].present)
970 pi_release(pt[unit].pi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 goto out;
972 }
Andrew Morton829d5f62006-03-28 01:56:18 -0800973 major = err;
gregkh@suse.dedeb36972005-03-23 09:52:10 -0800974 pt_class = class_create(THIS_MODULE, "pt");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (IS_ERR(pt_class)) {
976 err = PTR_ERR(pt_class);
977 goto out_chrdev;
978 }
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 for (unit = 0; unit < PT_UNITS; unit++)
981 if (pt[unit].present) {
Greg Kroah-Hartmanf79f0602008-05-21 12:52:33 -0700982 device_create_drvdata(pt_class, NULL,
983 MKDEV(major, unit), NULL,
984 "pt%d", unit);
985 device_create_drvdata(pt_class, NULL,
986 MKDEV(major, unit + 128), NULL,
987 "pt%dn", unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989 goto out;
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991out_chrdev:
992 unregister_chrdev(major, "pt");
993out:
994 return err;
995}
996
997static void __exit pt_exit(void)
998{
999 int unit;
1000 for (unit = 0; unit < PT_UNITS; unit++)
1001 if (pt[unit].present) {
Tony Jonesaa275822007-09-25 02:03:03 +02001002 device_destroy(pt_class, MKDEV(major, unit));
1003 device_destroy(pt_class, MKDEV(major, unit + 128));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 }
gregkh@suse.dedeb36972005-03-23 09:52:10 -08001005 class_destroy(pt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 unregister_chrdev(major, name);
1007 for (unit = 0; unit < PT_UNITS; unit++)
1008 if (pt[unit].present)
1009 pi_release(pt[unit].pi);
1010}
1011
1012MODULE_LICENSE("GPL");
1013module_init(pt_init)
1014module_exit(pt_exit)