1 /* 2 * drivers/s390/char/tape_char.c 3 * character device frontend for tape device driver 4 * 5 * S390 and zSeries version 6 * Copyright IBM Corp. 2001,2006 7 * Author(s): Carsten Otte <cotte@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 10 * Martin Schwidefsky <schwidefsky@de.ibm.com> 11 */ 12 13 #define KMSG_COMPONENT "tape" 14 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 15 16 #include <linux/module.h> 17 #include <linux/types.h> 18 #include <linux/proc_fs.h> 19 #include <linux/mtio.h> 20 #include <linux/smp_lock.h> 21 22 #include <asm/uaccess.h> 23 24 #define TAPE_DBF_AREA tape_core_dbf 25 26 #include "tape.h" 27 #include "tape_std.h" 28 #include "tape_class.h" 29 30 #define TAPECHAR_MAJOR 0 /* get dynamic major */ 31 32 /* 33 * file operation structure for tape character frontend 34 */ 35 static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *); 36 static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); 37 static int tapechar_open(struct inode *,struct file *); 38 static int tapechar_release(struct inode *,struct file *); 39 static long tapechar_ioctl(struct file *, unsigned int, unsigned long); 40 static long tapechar_compat_ioctl(struct file *, unsigned int, 41 unsigned long); 42 43 static const struct file_operations tape_fops = 44 { 45 .owner = THIS_MODULE, 46 .read = tapechar_read, 47 .write = tapechar_write, 48 .unlocked_ioctl = tapechar_ioctl, 49 .compat_ioctl = tapechar_compat_ioctl, 50 .open = tapechar_open, 51 .release = tapechar_release, 52 }; 53 54 static int tapechar_major = TAPECHAR_MAJOR; 55 56 /* 57 * This function is called for every new tapedevice 58 */ 59 int 60 tapechar_setup_device(struct tape_device * device) 61 { 62 char device_name[20]; 63 64 sprintf(device_name, "ntibm%i", device->first_minor / 2); 65 device->nt = register_tape_dev( 66 &device->cdev->dev, 67 MKDEV(tapechar_major, device->first_minor), 68 &tape_fops, 69 device_name, 70 "non-rewinding" 71 ); 72 device_name[0] = 'r'; 73 device->rt = register_tape_dev( 74 &device->cdev->dev, 75 MKDEV(tapechar_major, device->first_minor + 1), 76 &tape_fops, 77 device_name, 78 "rewinding" 79 ); 80 81 return 0; 82 } 83 84 void 85 tapechar_cleanup_device(struct tape_device *device) 86 { 87 unregister_tape_dev(&device->cdev->dev, device->rt); 88 device->rt = NULL; 89 unregister_tape_dev(&device->cdev->dev, device->nt); 90 device->nt = NULL; 91 } 92 93 static int 94 tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) 95 { 96 struct idal_buffer *new; 97 98 if (device->char_data.idal_buf != NULL && 99 device->char_data.idal_buf->size == block_size) 100 return 0; 101 102 if (block_size > MAX_BLOCKSIZE) { 103 DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n", 104 block_size, MAX_BLOCKSIZE); 105 return -EINVAL; 106 } 107 108 /* The current idal buffer is not correct. Allocate a new one. */ 109 new = idal_buffer_alloc(block_size, 0); 110 if (IS_ERR(new)) 111 return -ENOMEM; 112 113 if (device->char_data.idal_buf != NULL) 114 idal_buffer_free(device->char_data.idal_buf); 115 116 device->char_data.idal_buf = new; 117 118 return 0; 119 } 120 121 /* 122 * Tape device read function 123 */ 124 static ssize_t 125 tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) 126 { 127 struct tape_device *device; 128 struct tape_request *request; 129 size_t block_size; 130 int rc; 131 132 DBF_EVENT(6, "TCHAR:read\n"); 133 device = (struct tape_device *) filp->private_data; 134 135 /* 136 * If the tape isn't terminated yet, do it now. And since we then 137 * are at the end of the tape there wouldn't be anything to read 138 * anyways. So we return immediatly. 139 */ 140 if(device->required_tapemarks) { 141 return tape_std_terminate_write(device); 142 } 143 144 /* Find out block size to use */ 145 if (device->char_data.block_size != 0) { 146 if (count < device->char_data.block_size) { 147 DBF_EVENT(3, "TCHAR:read smaller than block " 148 "size was requested\n"); 149 return -EINVAL; 150 } 151 block_size = device->char_data.block_size; 152 } else { 153 block_size = count; 154 } 155 156 rc = tapechar_check_idalbuffer(device, block_size); 157 if (rc) 158 return rc; 159 160 #ifdef CONFIG_S390_TAPE_BLOCK 161 /* Changes position. */ 162 device->blk_data.medium_changed = 1; 163 #endif 164 165 DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size); 166 /* Let the discipline build the ccw chain. */ 167 request = device->discipline->read_block(device, block_size); 168 if (IS_ERR(request)) 169 return PTR_ERR(request); 170 /* Execute it. */ 171 rc = tape_do_io(device, request); 172 if (rc == 0) { 173 rc = block_size - request->rescnt; 174 DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); 175 /* Copy data from idal buffer to user space. */ 176 if (idal_buffer_to_user(device->char_data.idal_buf, 177 data, rc) != 0) 178 rc = -EFAULT; 179 } 180 tape_free_request(request); 181 return rc; 182 } 183 184 /* 185 * Tape device write function 186 */ 187 static ssize_t 188 tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos) 189 { 190 struct tape_device *device; 191 struct tape_request *request; 192 size_t block_size; 193 size_t written; 194 int nblocks; 195 int i, rc; 196 197 DBF_EVENT(6, "TCHAR:write\n"); 198 device = (struct tape_device *) filp->private_data; 199 /* Find out block size and number of blocks */ 200 if (device->char_data.block_size != 0) { 201 if (count < device->char_data.block_size) { 202 DBF_EVENT(3, "TCHAR:write smaller than block " 203 "size was requested\n"); 204 return -EINVAL; 205 } 206 block_size = device->char_data.block_size; 207 nblocks = count / block_size; 208 } else { 209 block_size = count; 210 nblocks = 1; 211 } 212 213 rc = tapechar_check_idalbuffer(device, block_size); 214 if (rc) 215 return rc; 216 217 #ifdef CONFIG_S390_TAPE_BLOCK 218 /* Changes position. */ 219 device->blk_data.medium_changed = 1; 220 #endif 221 222 DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size); 223 DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks); 224 /* Let the discipline build the ccw chain. */ 225 request = device->discipline->write_block(device, block_size); 226 if (IS_ERR(request)) 227 return PTR_ERR(request); 228 rc = 0; 229 written = 0; 230 for (i = 0; i < nblocks; i++) { 231 /* Copy data from user space to idal buffer. */ 232 if (idal_buffer_from_user(device->char_data.idal_buf, 233 data, block_size)) { 234 rc = -EFAULT; 235 break; 236 } 237 rc = tape_do_io(device, request); 238 if (rc) 239 break; 240 DBF_EVENT(6, "TCHAR:wbytes: %lx\n", 241 block_size - request->rescnt); 242 written += block_size - request->rescnt; 243 if (request->rescnt != 0) 244 break; 245 data += block_size; 246 } 247 tape_free_request(request); 248 if (rc == -ENOSPC) { 249 /* 250 * Ok, the device has no more space. It has NOT written 251 * the block. 252 */ 253 if (device->discipline->process_eov) 254 device->discipline->process_eov(device); 255 if (written > 0) 256 rc = 0; 257 258 } 259 260 /* 261 * After doing a write we always need two tapemarks to correctly 262 * terminate the tape (one to terminate the file, the second to 263 * flag the end of recorded data. 264 * Since process_eov positions the tape in front of the written 265 * tapemark it doesn't hurt to write two marks again. 266 */ 267 if (!rc) 268 device->required_tapemarks = 2; 269 270 return rc ? rc : written; 271 } 272 273 /* 274 * Character frontend tape device open function. 275 */ 276 static int 277 tapechar_open (struct inode *inode, struct file *filp) 278 { 279 struct tape_device *device; 280 int minor, rc; 281 282 DBF_EVENT(6, "TCHAR:open: %i:%i\n", 283 imajor(filp->f_path.dentry->d_inode), 284 iminor(filp->f_path.dentry->d_inode)); 285 286 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) 287 return -ENODEV; 288 289 minor = iminor(filp->f_path.dentry->d_inode); 290 device = tape_find_device(minor / TAPE_MINORS_PER_DEV); 291 if (IS_ERR(device)) { 292 DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n"); 293 return PTR_ERR(device); 294 } 295 296 rc = tape_open(device); 297 if (rc == 0) { 298 filp->private_data = device; 299 nonseekable_open(inode, filp); 300 } else 301 tape_put_device(device); 302 303 return rc; 304 } 305 306 /* 307 * Character frontend tape device release function. 308 */ 309 310 static int 311 tapechar_release(struct inode *inode, struct file *filp) 312 { 313 struct tape_device *device; 314 315 DBF_EVENT(6, "TCHAR:release: %x\n", iminor(inode)); 316 device = (struct tape_device *) filp->private_data; 317 318 /* 319 * If this is the rewinding tape minor then rewind. In that case we 320 * write all required tapemarks. Otherwise only one to terminate the 321 * file. 322 */ 323 if ((iminor(inode) & 1) != 0) { 324 if (device->required_tapemarks) 325 tape_std_terminate_write(device); 326 tape_mtop(device, MTREW, 1); 327 } else { 328 if (device->required_tapemarks > 1) { 329 if (tape_mtop(device, MTWEOF, 1) == 0) 330 device->required_tapemarks--; 331 } 332 } 333 334 if (device->char_data.idal_buf != NULL) { 335 idal_buffer_free(device->char_data.idal_buf); 336 device->char_data.idal_buf = NULL; 337 } 338 tape_release(device); 339 filp->private_data = NULL; 340 tape_put_device(device); 341 342 return 0; 343 } 344 345 /* 346 * Tape device io controls. 347 */ 348 static int 349 __tapechar_ioctl(struct tape_device *device, 350 unsigned int no, unsigned long data) 351 { 352 int rc; 353 354 if (no == MTIOCTOP) { 355 struct mtop op; 356 357 if (copy_from_user(&op, (char __user *) data, sizeof(op)) != 0) 358 return -EFAULT; 359 if (op.mt_count < 0) 360 return -EINVAL; 361 362 /* 363 * Operations that change tape position should write final 364 * tapemarks. 365 */ 366 switch (op.mt_op) { 367 case MTFSF: 368 case MTBSF: 369 case MTFSR: 370 case MTBSR: 371 case MTREW: 372 case MTOFFL: 373 case MTEOM: 374 case MTRETEN: 375 case MTBSFM: 376 case MTFSFM: 377 case MTSEEK: 378 #ifdef CONFIG_S390_TAPE_BLOCK 379 device->blk_data.medium_changed = 1; 380 #endif 381 if (device->required_tapemarks) 382 tape_std_terminate_write(device); 383 default: 384 ; 385 } 386 rc = tape_mtop(device, op.mt_op, op.mt_count); 387 388 if (op.mt_op == MTWEOF && rc == 0) { 389 if (op.mt_count > device->required_tapemarks) 390 device->required_tapemarks = 0; 391 else 392 device->required_tapemarks -= op.mt_count; 393 } 394 return rc; 395 } 396 if (no == MTIOCPOS) { 397 /* MTIOCPOS: query the tape position. */ 398 struct mtpos pos; 399 400 rc = tape_mtop(device, MTTELL, 1); 401 if (rc < 0) 402 return rc; 403 pos.mt_blkno = rc; 404 if (copy_to_user((char __user *) data, &pos, sizeof(pos)) != 0) 405 return -EFAULT; 406 return 0; 407 } 408 if (no == MTIOCGET) { 409 /* MTIOCGET: query the tape drive status. */ 410 struct mtget get; 411 412 memset(&get, 0, sizeof(get)); 413 get.mt_type = MT_ISUNKNOWN; 414 get.mt_resid = 0 /* device->devstat.rescnt */; 415 get.mt_dsreg = device->tape_state; 416 /* FIXME: mt_gstat, mt_erreg, mt_fileno */ 417 get.mt_gstat = 0; 418 get.mt_erreg = 0; 419 get.mt_fileno = 0; 420 get.mt_gstat = device->tape_generic_status; 421 422 if (device->medium_state == MS_LOADED) { 423 rc = tape_mtop(device, MTTELL, 1); 424 425 if (rc < 0) 426 return rc; 427 428 if (rc == 0) 429 get.mt_gstat |= GMT_BOT(~0); 430 431 get.mt_blkno = rc; 432 } 433 434 if (copy_to_user((char __user *) data, &get, sizeof(get)) != 0) 435 return -EFAULT; 436 437 return 0; 438 } 439 /* Try the discipline ioctl function. */ 440 if (device->discipline->ioctl_fn == NULL) 441 return -EINVAL; 442 return device->discipline->ioctl_fn(device, no, data); 443 } 444 445 static long 446 tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) 447 { 448 struct tape_device *device; 449 long rc; 450 451 DBF_EVENT(6, "TCHAR:ioct\n"); 452 453 device = (struct tape_device *) filp->private_data; 454 mutex_lock(&device->mutex); 455 rc = __tapechar_ioctl(device, no, data); 456 mutex_unlock(&device->mutex); 457 return rc; 458 } 459 460 static long 461 tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) 462 { 463 struct tape_device *device = filp->private_data; 464 int rval = -ENOIOCTLCMD; 465 466 if (device->discipline->ioctl_fn) { 467 mutex_lock(&device->mutex); 468 rval = device->discipline->ioctl_fn(device, no, data); 469 mutex_unlock(&device->mutex); 470 if (rval == -EINVAL) 471 rval = -ENOIOCTLCMD; 472 } 473 474 return rval; 475 } 476 477 /* 478 * Initialize character device frontend. 479 */ 480 int 481 tapechar_init (void) 482 { 483 dev_t dev; 484 485 if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0) 486 return -1; 487 488 tapechar_major = MAJOR(dev); 489 490 return 0; 491 } 492 493 /* 494 * cleanup 495 */ 496 void 497 tapechar_exit(void) 498 { 499 unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); 500 } 501