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