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