2 /***************************************************************************
4 * drivers/s390/char/tapechar.c
5 * character device frontend for tape device driver
7 * S390 and zSeries version
8 * Copyright (C) 2001 IBM Corporation
9 * Author(s): Carsten Otte <cotte@de.ibm.com>
10 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
13 ****************************************************************************
17 #include <linux/config.h>
18 #include <linux/version.h>
19 #include <linux/types.h>
20 #include <linux/proc_fs.h>
21 #include <asm/ccwcache.h> /* CCW allocations */
22 #include <asm/s390dyn.h>
23 #include <asm/debug.h>
24 #include <linux/mtio.h>
25 #include <asm/uaccess.h>
26 #include <linux/compatmac.h>
28 #define __NO_VERSION__
29 #include <linux/module.h>
34 #define PRINTK_HEADER "TCHAR:"
37 * file operation structure for tape devices
39 static struct file_operations tape_fops =
41 // owner : THIS_MODULE,
42 llseek:NULL, /* lseek - default */
43 read:tape_read, /* read */
44 write:tape_write, /* write */
45 readdir:NULL, /* readdir - bad */
47 ioctl:tape_ioctl, /* ioctl */
49 open:tape_open, /* open */
50 flush:NULL, /* flush */
51 release:tape_release, /* release */
52 fsync:NULL, /* fsync */
53 fasync:NULL, /* fasync */
57 int tape_major = TAPE_MAJOR;
59 #ifdef CONFIG_DEVFS_FS
61 tapechar_mkdevfstree (tape_info_t* ti) {
62 ti->devfs_char_dir=devfs_mk_dir (ti->devfs_dir, "char", ti);
63 ti->devfs_nonrewinding=devfs_register(ti->devfs_char_dir, "nonrewinding",
64 DEVFS_FL_DEFAULT,tape_major,
65 ti->nor_minor, TAPECHAR_DEFAULTMODE,
67 ti->devfs_rewinding=devfs_register(ti->devfs_char_dir, "rewinding",
68 DEVFS_FL_DEFAULT, tape_major, ti->rew_minor,
69 TAPECHAR_DEFAULTMODE, &tape_fops, ti);
73 tapechar_rmdevfstree (tape_info_t* ti) {
74 devfs_unregister(ti->devfs_nonrewinding);
75 devfs_unregister(ti->devfs_rewinding);
76 devfs_unregister(ti->devfs_char_dir);
81 tapechar_setup (tape_info_t * ti)
83 #ifdef CONFIG_DEVFS_FS
84 tapechar_mkdevfstree(ti);
92 tape_frontend_t *charfront,*temp;
97 /* Register the tape major number to the kernel */
98 #ifdef CONFIG_DEVFS_FS
99 result = devfs_register_chrdev (tape_major, "tape", &tape_fops);
101 result = register_chrdev (tape_major, "tape", &tape_fops);
105 PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tape_major);
107 debug_text_event (tape_debug_area,3,"c:initfail");
108 debug_text_event (tape_debug_area,3,"regchrfail");
109 #endif /* TAPE_DEBUG */
110 panic ("no major number available for tape char device");
113 tape_major = result; /* accept dynamic major number */
114 PRINT_WARN (KERN_ERR " tape gets major %d for character device\n", result);
115 charfront = kmalloc (sizeof (tape_frontend_t), GFP_KERNEL);
116 if (charfront == NULL) {
118 debug_text_event (tape_debug_area,3,"c:initfail");
119 debug_text_event (tape_debug_area,3,"no mem");
120 #endif /* TAPE_DEBUG */
121 panic ("no major number available for tape char device");
123 charfront->device_setup = tapechar_setup;
124 #ifdef CONFIG_DEVFS_FS
125 charfront->mkdevfstree = tapechar_mkdevfstree;
126 charfront->rmdevfstree = tapechar_rmdevfstree;
129 debug_text_event (tape_debug_area,3,"c:init ok");
130 #endif /* TAPE_DEBUG */
131 charfront->next=NULL;
132 if (first_frontend==NULL) {
133 first_frontend=charfront;
136 while (temp->next!=NULL)
138 temp->next=charfront;
148 tapechar_uninit (void)
150 unregister_chrdev (tape_major, "tape");
154 * Tape device read function
157 tape_read (struct file *filp, char *data, size_t count, loff_t * ppos)
166 debug_text_event (tape_debug_area,6,"c:read");
167 #endif /* TAPE_DEBUG */
168 ti = first_tape_info;
169 while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))
170 ti = (tape_info_t *) ti->next;
173 debug_text_event (tape_debug_area,6,"c:nodev");
174 #endif /* TAPE_DEBUG */
177 if (ppos != &filp->f_pos) {
178 /* "A request was outside the capabilities of the device." */
180 debug_text_event (tape_debug_area,6,"c:ppos wrong");
181 #endif /* TAPE_DEBUG */
182 return -EOVERFLOW; /* errno=75 Value too large for def. data type */
184 if (ti->block_size == 0) {
187 block_size = ti->block_size;
190 debug_text_event (tape_debug_area,6,"c:nbytes:");
191 debug_int_event (tape_debug_area,6,block_size);
193 cqr = ti->discipline->read_block (data, block_size, ti);
197 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
200 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
202 tapestate_set(ti,TS_IDLE);
204 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
207 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
208 wait_event (ti->wq,ti->wanna_wakeup);
210 ti->discipline->free_read_block (cqr, ti);
211 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
212 if (tapestate_get (ti) == TS_FAILED) {
213 tapestate_set (ti, TS_IDLE);
214 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
217 if (tapestate_get (ti) == TS_NOT_OPER) {
218 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
220 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
223 if (tapestate_get (ti) != TS_DONE) {
224 tapestate_set (ti, TS_IDLE);
225 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
228 tapestate_set (ti, TS_IDLE);
229 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
231 debug_text_event (tape_debug_area,6,"c:rbytes:");
232 debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);
233 #endif /* TAPE_DEBUG */
234 *ppos = pos + (block_size - ti->devstat.rescnt);
235 return block_size - ti->devstat.rescnt;
239 * Tape device write function
242 tape_write (struct file *filp, const char *data, size_t count, loff_t * ppos)
253 debug_text_event (tape_debug_area,6,"c:write");
255 ti = first_tape_info;
256 while ((ti != NULL) && (ti->nor_filp != filp) && (ti->rew_filp != filp))
257 ti = (tape_info_t *) ti->next;
260 if (ppos != &filp->f_pos) {
261 /* "A request was outside the capabilities of the device." */
263 debug_text_event (tape_debug_area,6,"c:ppos wrong");
265 return -EOVERFLOW; /* errno=75 Value too large for def. data type */
267 if ((ti->block_size != 0) && (count % ti->block_size != 0))
269 if (ti->block_size == 0) {
273 block_size = ti->block_size;
274 nblocks = count / (ti->block_size);
277 debug_text_event (tape_debug_area,6,"c:nbytes:");
278 debug_int_event (tape_debug_area,6,block_size);
279 debug_text_event (tape_debug_area,6,"c:nblocks:");
280 debug_int_event (tape_debug_area,6,nblocks);
282 for (i = 0; i < nblocks; i++) {
283 cqr = ti->discipline->write_block (data + i * block_size, block_size, ti);
287 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
290 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
291 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
292 wait_event_interruptible (ti->wq,ti->wanna_wakeup);
294 ti->discipline->free_write_block (cqr, ti);
295 if (signal_pending (current)) {
296 tapestate_set (ti, TS_IDLE);
299 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
300 if (tapestate_get (ti) == TS_FAILED) {
301 tapestate_set (ti, TS_IDLE);
302 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
303 if ((ti->rc==-ENOSPC) && (i!=0))
307 if (tapestate_get (ti) == TS_NOT_OPER) {
308 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
310 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
313 if (tapestate_get (ti) != TS_DONE) {
314 tapestate_set (ti, TS_IDLE);
315 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
318 tapestate_set (ti, TS_IDLE);
319 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
321 debug_text_event (tape_debug_area,6,"c:wbytes:");
322 debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);
324 written += block_size - ti->devstat.rescnt;
325 if (ti->devstat.rescnt > 0) {
326 *ppos = pos + written;
331 debug_text_event (tape_debug_area,6,"c:wtotal:");
332 debug_int_event (tape_debug_area,6,written);
334 *ppos = pos + written;
339 tape_mtioctop (struct file *filp, short mt_op, int mt_count)
342 ccw_req_t *cqr = NULL;
346 debug_text_event (tape_debug_area,6,"c:mtio");
347 debug_text_event (tape_debug_area,6,"c:ioop:");
348 debug_int_event (tape_debug_area,6,mt_op);
349 debug_text_event (tape_debug_area,6,"c:arg:");
350 debug_int_event (tape_debug_area,6,mt_count);
352 ti = first_tape_info;
353 while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))
354 ti = (tape_info_t *) ti->next;
358 case MTREW: // rewind
360 cqr = ti->discipline->mtrew (ti, mt_count);
362 case MTOFFL: // put drive offline
364 cqr = ti->discipline->mtoffl (ti, mt_count);
366 case MTUNLOAD: // unload the tape
368 cqr = ti->discipline->mtunload (ti, mt_count);
370 case MTWEOF: // write tapemark
372 cqr = ti->discipline->mtweof (ti, mt_count);
374 case MTFSF: // forward space file
376 cqr = ti->discipline->mtfsf (ti, mt_count);
378 case MTBSF: // backward space file
380 cqr = ti->discipline->mtbsf (ti, mt_count);
382 case MTFSFM: // forward space file, stop at BOT side
384 cqr = ti->discipline->mtfsfm (ti, mt_count);
386 case MTBSFM: // backward space file, stop at BOT side
388 cqr = ti->discipline->mtbsfm (ti, mt_count);
390 case MTFSR: // forward space file
392 cqr = ti->discipline->mtfsr (ti, mt_count);
394 case MTBSR: // backward space file
396 cqr = ti->discipline->mtbsr (ti, mt_count);
399 cqr = ti->discipline->mtnop (ti, mt_count);
401 case MTEOM: // postion at the end of portion
403 case MTRETEN: // retension the tape
405 cqr = ti->discipline->mteom (ti, mt_count);
408 cqr = ti->discipline->mterase (ti, mt_count);
411 cqr = ti->discipline->mtsetdensity (ti, mt_count);
414 cqr = ti->discipline->mtseek (ti, mt_count);
417 cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
420 cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
423 cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
426 cqr = ti->discipline->mtload (ti, mt_count);
427 if (cqr!=NULL) break; // if backend driver has an load function ->use it
428 // if no medium is in, wait until it gets inserted
429 if (ti->medium_is_unloaded) {
430 wait_event_interruptible (ti->wq,ti->medium_is_unloaded==0);
434 cqr = ti->discipline->mtcompression (ti, mt_count);
437 cqr = ti->discipline->mtsetpart (ti, mt_count);
440 cqr = ti->discipline->mtmkpart (ti, mt_count);
442 case MTTELL: // return number of block relative to current file
444 cqr = ti->discipline->mttell (ti, mt_count);
447 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
448 ti->block_size = mt_count;
449 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
451 debug_text_event (tape_debug_area,6,"c:setblk:");
452 debug_int_event (tape_debug_area,6,mt_count);
456 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
457 ti->kernbuf = ti->userbuf = NULL;
458 tapestate_set (ti, TS_IDLE);
460 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
462 debug_text_event (tape_debug_area,6,"c:devreset:");
463 debug_int_event (tape_debug_area,6,ti->blk_minor);
468 debug_text_event (tape_debug_area,6,"c:inv.mtio");
474 debug_text_event (tape_debug_area,6,"c:ccwg fail");
478 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
481 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
482 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
483 wait_event_interruptible (ti->wq,ti->wanna_wakeup);
485 if (ti->kernbuf != NULL) {
489 tape_free_request (cqr);
490 // if medium was unloaded, update the corresponding variable.
494 ti->medium_is_unloaded=1;
496 if (signal_pending (current)) {
497 tapestate_set (ti, TS_IDLE);
500 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
501 if (((mt_op == MTEOM) || (mt_op == MTRETEN)) && (tapestate_get (ti) == TS_FAILED))
502 tapestate_set (ti, TS_DONE);
503 if (tapestate_get (ti) == TS_FAILED) {
504 tapestate_set (ti, TS_IDLE);
505 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
508 if (tapestate_get (ti) == TS_NOT_OPER) {
509 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
511 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
514 if (tapestate_get (ti) != TS_DONE) {
515 tapestate_set (ti, TS_IDLE);
516 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
519 tapestate_set (ti, TS_IDLE);
520 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
522 case MTRETEN: //need to rewind the tape after moving to eom
524 return tape_mtioctop (filp, MTREW, 1);
525 case MTFSFM: //need to skip back over the filemark
527 return tape_mtioctop (filp, MTBSFM, 1);
528 case MTBSF: //need to skip forward over the filemark
530 return tape_mtioctop (filp, MTFSF, 1);
533 debug_text_event (tape_debug_area,6,"c:mtio done");
539 * Tape device io controls.
542 tape_ioctl (struct inode *inode, struct file *filp,
543 unsigned int cmd, unsigned long arg)
548 struct mtop op; /* structure for MTIOCTOP */
549 struct mtpos pos; /* structure for MTIOCPOS */
554 debug_text_event (tape_debug_area,6,"c:ioct");
556 ti = first_tape_info;
557 while ((ti != NULL) &&
558 (ti->rew_minor != MINOR (inode->i_rdev)) &&
559 (ti->nor_minor != MINOR (inode->i_rdev)))
560 ti = (tape_info_t *) ti->next;
563 debug_text_event (tape_debug_area,6,"c:nodev");
567 // check for discipline ioctl overloading
568 if ((rc = ti->discipline->discipline_ioctl_overload (inode, filp, cmd, arg))
571 debug_text_event (tape_debug_area,6,"c:ioverloa");
577 case MTIOCTOP: /* tape op command */
578 if (copy_from_user (&op, (char *) arg, sizeof (struct mtop))) {
581 return (tape_mtioctop (filp, op.mt_op, op.mt_count));
582 case MTIOCPOS: /* query tape position */
583 cqr = ti->discipline->mttell (ti, 0);
584 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
587 do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
588 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
589 wait_event_interruptible (ti->wq,ti->wanna_wakeup);
590 pos.mt_blkno = ti->rc;
592 if (ti->kernbuf != NULL) {
596 tape_free_request (cqr);
597 if (signal_pending (current)) {
598 tapestate_set (ti, TS_IDLE);
601 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
602 tapestate_set (ti, TS_IDLE);
603 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
604 if (copy_to_user ((char *) arg, &pos, sizeof (struct mtpos)))
608 get.mt_erreg = ti->rc;
609 cqr = ti->discipline->mttell (ti, 0);
610 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
613 do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
614 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
615 wait_event_interruptible (ti->wq,ti->wanna_wakeup);
616 get.mt_blkno = ti->rc;
618 get.mt_type = MT_ISUNKNOWN;
619 get.mt_resid = ti->devstat.rescnt;
620 get.mt_dsreg = ti->devstat.ii.sense.data[3];
622 if (ti->devstat.ii.sense.data[1] & 0x08)
623 get.mt_gstat &= GMT_BOT (1); // BOT
625 if (ti->devstat.ii.sense.data[1] & 0x02)
626 get.mt_gstat &= GMT_WR_PROT (1); // write protected
628 if (ti->devstat.ii.sense.data[1] & 0x40)
629 get.mt_gstat &= GMT_ONLINE (1); //drive online
632 if (ti->kernbuf != NULL) {
636 tape_free_request (cqr);
637 if (signal_pending (current)) {
638 tapestate_set (ti, TS_IDLE);
641 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
642 tapestate_set (ti, TS_IDLE);
643 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
644 if (copy_to_user ((char *) arg, &get, sizeof (struct mtget)))
649 debug_text_event (tape_debug_area,3,"c:ioct inv");
656 * Tape device open function.
659 tape_open (struct inode *inode, struct file *filp)
665 inode = filp->f_dentry->d_inode;
666 ti = first_tape_info;
667 while ((ti != NULL) &&
668 (ti->rew_minor != MINOR (inode->i_rdev)) &&
669 (ti->nor_minor != MINOR (inode->i_rdev)))
670 ti = (tape_info_t *) ti->next;
674 debug_text_event (tape_debug_area,6,"c:open:");
675 debug_int_event (tape_debug_area,6,ti->blk_minor);
677 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
678 if (tapestate_get (ti) != TS_UNUSED) {
679 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
681 debug_text_event (tape_debug_area,6,"c:dbusy");
685 tapestate_set (ti, TS_IDLE);
686 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
688 dev = MKDEV (tape_major, MINOR (inode->i_rdev)); /* Get the device */
689 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
690 if (ti->rew_minor == MINOR (inode->i_rdev))
691 ti->rew_filp = filp; /* save for later reference */
694 filp->private_data = ti; /* save the dev.info for later reference */
695 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
704 * Tape device release function.
707 tape_release (struct inode *inode, struct file *filp)
710 tape_info_t *ti,*lastti;
711 ccw_req_t *cqr = NULL;
714 ti = first_tape_info;
715 while ((ti != NULL) && (ti->rew_minor != MINOR (inode->i_rdev)) && (ti->nor_minor != MINOR (inode->i_rdev)))
716 ti = (tape_info_t *) ti->next;
717 if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) {
718 if (ti==first_tape_info) {
719 first_tape_info=ti->next;
721 lastti=first_tape_info;
722 while (lastti->next!=ti) lastti=lastti->next;
723 lastti->next=ti->next;
728 if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {
730 debug_text_event (tape_debug_area,6,"c:notidle!");
732 rc = -ENXIO; /* error in tape_release */
736 debug_text_event (tape_debug_area,6,"c:release:");
737 debug_int_event (tape_debug_area,6,ti->blk_minor);
739 if (ti->rew_minor == MINOR (inode->i_rdev)) {
740 cqr = ti->discipline->mtrew (ti, 1);
743 debug_text_event (tape_debug_area,6,"c:rewrelea");
745 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
746 tapestate_set (ti, TS_REW_RELEASE_INIT);
749 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
750 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
751 wait_event (ti->wq,ti->wanna_wakeup);
753 tape_free_request (cqr);
756 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
757 tapestate_set (ti, TS_UNUSED);
758 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);