aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/paride/pt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/block/paride/pt.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/block/paride/pt.c')
-rw-r--r--drivers/block/paride/pt.c1024
1 files changed, 1024 insertions, 0 deletions
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
new file mode 100644
index 000000000000..8fbd6922fe0d
--- /dev/null
+++ b/drivers/block/paride/pt.c
@@ -0,0 +1,1024 @@
1/*
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>
144#include <linux/devfs_fs_kernel.h>
145#include <linux/delay.h>
146#include <linux/slab.h>
147#include <linux/mtio.h>
148#include <linux/device.h>
149
150#include <asm/uaccess.h>
151
152module_param(verbose, bool, 0);
153module_param(major, int, 0);
154module_param(name, charp, 0);
155module_param_array(drive0, int, NULL, 0);
156module_param_array(drive1, int, NULL, 0);
157module_param_array(drive2, int, NULL, 0);
158module_param_array(drive3, int, NULL, 0);
159
160#include "paride.h"
161
162#define PT_MAX_RETRIES 5
163#define PT_TMO 3000 /* interrupt timeout in jiffies */
164#define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
165#define PT_RESET_TMO 30 /* 30 seconds */
166#define PT_READY_TMO 60 /* 60 seconds */
167#define PT_REWIND_TMO 1200 /* 20 minutes */
168
169#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
170
171#define STAT_ERR 0x00001
172#define STAT_INDEX 0x00002
173#define STAT_ECC 0x00004
174#define STAT_DRQ 0x00008
175#define STAT_SEEK 0x00010
176#define STAT_WRERR 0x00020
177#define STAT_READY 0x00040
178#define STAT_BUSY 0x00080
179#define STAT_SENSE 0x1f000
180
181#define ATAPI_TEST_READY 0x00
182#define ATAPI_REWIND 0x01
183#define ATAPI_REQ_SENSE 0x03
184#define ATAPI_READ_6 0x08
185#define ATAPI_WRITE_6 0x0a
186#define ATAPI_WFM 0x10
187#define ATAPI_IDENTIFY 0x12
188#define ATAPI_MODE_SENSE 0x1a
189#define ATAPI_LOG_SENSE 0x4d
190
191static int pt_open(struct inode *inode, struct file *file);
192static int pt_ioctl(struct inode *inode, struct file *file,
193 unsigned int cmd, unsigned long arg);
194static 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
235static struct file_operations pt_fops = {
236 .owner = THIS_MODULE,
237 .read = pt_read,
238 .write = pt_write,
239 .ioctl = pt_ioctl,
240 .open = pt_open,
241 .release = pt_release,
242};
243
244/* sysfs class support */
245static struct class_simple *pt_class;
246
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{
386 current->state = TASK_INTERRUPTIBLE;
387 schedule_timeout(cs);
388}
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
654 if (unit >= PT_UNITS || (!tape->present))
655 return -ENODEV;
656
657 err = -EBUSY;
658 if (!atomic_dec_and_test(&tape->available))
659 goto out;
660
661 pt_identify(tape);
662
663 err = -ENODEV;
664 if (!tape->flags & PT_MEDIA)
665 goto out;
666
667 err = -EROFS;
668 if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2))
669 goto out;
670
671 if (!(iminor(inode) & 128))
672 tape->flags |= PT_REWIND;
673
674 err = -ENOMEM;
675 tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
676 if (tape->bufptr == NULL) {
677 printk("%s: buffer allocation failed\n", tape->name);
678 goto out;
679 }
680
681 file->private_data = tape;
682 return 0;
683
684out:
685 atomic_inc(&tape->available);
686 return err;
687}
688
689static int pt_ioctl(struct inode *inode, struct file *file,
690 unsigned int cmd, unsigned long arg)
691{
692 struct pt_unit *tape = file->private_data;
693 struct mtop __user *p = (void __user *)arg;
694 struct mtop mtop;
695
696 switch (cmd) {
697 case MTIOCTOP:
698 if (copy_from_user(&mtop, p, sizeof(struct mtop)))
699 return -EFAULT;
700
701 switch (mtop.mt_op) {
702
703 case MTREW:
704 pt_rewind(tape);
705 return 0;
706
707 case MTWEOF:
708 pt_write_fm(tape);
709 return 0;
710
711 default:
712 printk("%s: Unimplemented mt_op %d\n", tape->name,
713 mtop.mt_op);
714 return -EINVAL;
715 }
716
717 default:
718 printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd);
719 return -EINVAL;
720
721 }
722}
723
724static int
725pt_release(struct inode *inode, struct file *file)
726{
727 struct pt_unit *tape = file->private_data;
728
729 if (atomic_read(&tape->available) > 1)
730 return -EINVAL;
731
732 if (tape->flags & PT_WRITING)
733 pt_write_fm(tape);
734
735 if (tape->flags & PT_REWIND)
736 pt_rewind(tape);
737
738 kfree(tape->bufptr);
739 tape->bufptr = NULL;
740
741 atomic_inc(&tape->available);
742
743 return 0;
744
745}
746
747static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
748{
749 struct pt_unit *tape = filp->private_data;
750 struct pi_adapter *pi = tape->pi;
751 char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
752 int k, n, r, p, s, t, b;
753
754 if (!(tape->flags & (PT_READING | PT_WRITING))) {
755 tape->flags |= PT_READING;
756 if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))
757 return -EIO;
758 } else if (tape->flags & PT_WRITING)
759 return -EIO;
760
761 if (tape->flags & PT_EOF)
762 return 0;
763
764 t = 0;
765
766 while (count > 0) {
767
768 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))
769 return -EIO;
770
771 n = count;
772 if (n > 32768)
773 n = 32768; /* max per command */
774 b = (n - 1 + tape->bs) / tape->bs;
775 n = b * tape->bs; /* rounded up to even block */
776
777 rd_cmd[4] = b;
778
779 r = pt_command(tape, rd_cmd, n, "read");
780
781 mdelay(1);
782
783 if (r) {
784 pt_req_sense(tape, 0);
785 return -EIO;
786 }
787
788 while (1) {
789
790 r = pt_wait(tape, STAT_BUSY,
791 STAT_DRQ | STAT_ERR | STAT_READY,
792 DBMSG("read DRQ"), "");
793
794 if (r & STAT_SENSE) {
795 pi_disconnect(pi);
796 pt_req_sense(tape, 0);
797 return -EIO;
798 }
799
800 if (r)
801 tape->flags |= PT_EOF;
802
803 s = read_reg(pi, 7);
804
805 if (!(s & STAT_DRQ))
806 break;
807
808 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
809 p = (read_reg(pi, 2) & 3);
810 if (p != 2) {
811 pi_disconnect(pi);
812 printk("%s: Phase error on read: %d\n", tape->name,
813 p);
814 return -EIO;
815 }
816
817 while (n > 0) {
818 k = n;
819 if (k > PT_BUFSIZE)
820 k = PT_BUFSIZE;
821 pi_read_block(pi, tape->bufptr, k);
822 n -= k;
823 b = k;
824 if (b > count)
825 b = count;
826 if (copy_to_user(buf + t, tape->bufptr, b)) {
827 pi_disconnect(pi);
828 return -EFAULT;
829 }
830 t += b;
831 count -= b;
832 }
833
834 }
835 pi_disconnect(pi);
836 if (tape->flags & PT_EOF)
837 break;
838 }
839
840 return t;
841
842}
843
844static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
845{
846 struct pt_unit *tape = filp->private_data;
847 struct pi_adapter *pi = tape->pi;
848 char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
849 int k, n, r, p, s, t, b;
850
851 if (!(tape->flags & PT_WRITE_OK))
852 return -EROFS;
853
854 if (!(tape->flags & (PT_READING | PT_WRITING))) {
855 tape->flags |= PT_WRITING;
856 if (pt_atapi
857 (tape, wr_cmd, 0, NULL, "start buffer-available mode"))
858 return -EIO;
859 } else if (tape->flags & PT_READING)
860 return -EIO;
861
862 if (tape->flags & PT_EOF)
863 return -ENOSPC;
864
865 t = 0;
866
867 while (count > 0) {
868
869 if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))
870 return -EIO;
871
872 n = count;
873 if (n > 32768)
874 n = 32768; /* max per command */
875 b = (n - 1 + tape->bs) / tape->bs;
876 n = b * tape->bs; /* rounded up to even block */
877
878 wr_cmd[4] = b;
879
880 r = pt_command(tape, wr_cmd, n, "write");
881
882 mdelay(1);
883
884 if (r) { /* error delivering command only */
885 pt_req_sense(tape, 0);
886 return -EIO;
887 }
888
889 while (1) {
890
891 r = pt_wait(tape, STAT_BUSY,
892 STAT_DRQ | STAT_ERR | STAT_READY,
893 DBMSG("write DRQ"), NULL);
894
895 if (r & STAT_SENSE) {
896 pi_disconnect(pi);
897 pt_req_sense(tape, 0);
898 return -EIO;
899 }
900
901 if (r)
902 tape->flags |= PT_EOF;
903
904 s = read_reg(pi, 7);
905
906 if (!(s & STAT_DRQ))
907 break;
908
909 n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
910 p = (read_reg(pi, 2) & 3);
911 if (p != 0) {
912 pi_disconnect(pi);
913 printk("%s: Phase error on write: %d \n",
914 tape->name, p);
915 return -EIO;
916 }
917
918 while (n > 0) {
919 k = n;
920 if (k > PT_BUFSIZE)
921 k = PT_BUFSIZE;
922 b = k;
923 if (b > count)
924 b = count;
925 if (copy_from_user(tape->bufptr, buf + t, b)) {
926 pi_disconnect(pi);
927 return -EFAULT;
928 }
929 pi_write_block(pi, tape->bufptr, k);
930 t += b;
931 count -= b;
932 n -= k;
933 }
934
935 }
936 pi_disconnect(pi);
937 if (tape->flags & PT_EOF)
938 break;
939 }
940
941 return t;
942}
943
944static int __init pt_init(void)
945{
946 int unit, err = 0;
947
948 if (disable) {
949 err = -1;
950 goto out;
951 }
952
953 if (pt_detect()) {
954 err = -1;
955 goto out;
956 }
957
958 if (register_chrdev(major, name, &pt_fops)) {
959 printk("pt_init: unable to get major number %d\n", major);
960 for (unit = 0; unit < PT_UNITS; unit++)
961 if (pt[unit].present)
962 pi_release(pt[unit].pi);
963 err = -1;
964 goto out;
965 }
966 pt_class = class_simple_create(THIS_MODULE, "pt");
967 if (IS_ERR(pt_class)) {
968 err = PTR_ERR(pt_class);
969 goto out_chrdev;
970 }
971
972 devfs_mk_dir("pt");
973 for (unit = 0; unit < PT_UNITS; unit++)
974 if (pt[unit].present) {
975 class_simple_device_add(pt_class, MKDEV(major, unit),
976 NULL, "pt%d", unit);
977 err = devfs_mk_cdev(MKDEV(major, unit),
978 S_IFCHR | S_IRUSR | S_IWUSR,
979 "pt/%d", unit);
980 if (err) {
981 class_simple_device_remove(MKDEV(major, unit));
982 goto out_class;
983 }
984 class_simple_device_add(pt_class, MKDEV(major, unit + 128),
985 NULL, "pt%dn", unit);
986 err = devfs_mk_cdev(MKDEV(major, unit + 128),
987 S_IFCHR | S_IRUSR | S_IWUSR,
988 "pt/%dn", unit);
989 if (err) {
990 class_simple_device_remove(MKDEV(major, unit + 128));
991 goto out_class;
992 }
993 }
994 goto out;
995
996out_class:
997 class_simple_destroy(pt_class);
998out_chrdev:
999 unregister_chrdev(major, "pt");
1000out:
1001 return err;
1002}
1003
1004static void __exit pt_exit(void)
1005{
1006 int unit;
1007 for (unit = 0; unit < PT_UNITS; unit++)
1008 if (pt[unit].present) {
1009 class_simple_device_remove(MKDEV(major, unit));
1010 devfs_remove("pt/%d", unit);
1011 class_simple_device_remove(MKDEV(major, unit + 128));
1012 devfs_remove("pt/%dn", unit);
1013 }
1014 class_simple_destroy(pt_class);
1015 devfs_remove("pt");
1016 unregister_chrdev(major, name);
1017 for (unit = 0; unit < PT_UNITS; unit++)
1018 if (pt[unit].present)
1019 pi_release(pt[unit].pi);
1020}
1021
1022MODULE_LICENSE("GPL");
1023module_init(pt_init)
1024module_exit(pt_exit)