linux-old/drivers/block/paride/pt.c
<<
>>
Prefs
   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};
 129static int pt_drive_count;
 130
 131#define D_PRT   0
 132#define D_PRO   1
 133#define D_UNI   2
 134#define D_MOD   3
 135#define D_SLV   4
 136#define D_DLY   5
 137
 138#define DU              (*drives[unit])
 139
 140/* end of parameters */
 141
 142
 143#include <linux/module.h>
 144#include <linux/errno.h>
 145#include <linux/fs.h>
 146#include <linux/devfs_fs_kernel.h>
 147#include <linux/kernel.h>
 148#include <linux/delay.h>
 149#include <linux/slab.h>
 150#include <linux/mtio.h>
 151#include <linux/wait.h>
 152#include <linux/smp_lock.h>
 153
 154#include <asm/uaccess.h>
 155
 156#ifndef MODULE
 157
 158#include "setup.h"
 159
 160static STT pt_stt[5] = {{"drive0",6,drive0},
 161                        {"drive1",6,drive1},
 162                        {"drive2",6,drive2},
 163                        {"drive3",6,drive3},
 164                        {"disable",1,&disable}};
 165
 166void pt_setup( char *str, int *ints)
 167
 168{       generic_setup(pt_stt,5,str);
 169}
 170
 171#endif
 172
 173MODULE_PARM(verbose,"i");
 174MODULE_PARM(major,"i");
 175MODULE_PARM(name,"s");
 176MODULE_PARM(drive0,"1-6i");
 177MODULE_PARM(drive1,"1-6i");
 178MODULE_PARM(drive2,"1-6i");
 179MODULE_PARM(drive3,"1-6i");
 180
 181#include "paride.h"
 182
 183#define PT_MAX_RETRIES  5
 184#define PT_TMO          3000            /* interrupt timeout in jiffies */
 185#define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
 186#define PT_RESET_TMO    30              /* 30 seconds */
 187#define PT_READY_TMO    60              /* 60 seconds */
 188#define PT_REWIND_TMO   1200            /* 20 minutes */
 189
 190#define PT_SPIN         ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)  
 191
 192#define STAT_ERR        0x00001
 193#define STAT_INDEX      0x00002
 194#define STAT_ECC        0x00004
 195#define STAT_DRQ        0x00008
 196#define STAT_SEEK       0x00010
 197#define STAT_WRERR      0x00020
 198#define STAT_READY      0x00040
 199#define STAT_BUSY       0x00080
 200#define STAT_SENSE      0x1f000
 201
 202#define ATAPI_TEST_READY        0x00
 203#define ATAPI_REWIND            0x01
 204#define ATAPI_REQ_SENSE         0x03
 205#define ATAPI_READ_6            0x08
 206#define ATAPI_WRITE_6           0x0a
 207#define ATAPI_WFM               0x10
 208#define ATAPI_IDENTIFY          0x12
 209#define ATAPI_MODE_SENSE        0x1a
 210#define ATAPI_LOG_SENSE         0x4d
 211
 212int pt_init(void);
 213#ifdef MODULE
 214void cleanup_module( void );
 215#endif
 216
 217static int pt_open(struct inode *inode, struct file *file);
 218static int pt_ioctl(struct inode *inode,struct file *file,
 219                    unsigned int cmd, unsigned long arg);
 220static int pt_release (struct inode *inode, struct file *file);
 221static ssize_t pt_read(struct file * filp, char * buf, 
 222                       size_t count, loff_t *ppos);
 223static ssize_t pt_write(struct file * filp, const char * buf, 
 224                        size_t count, loff_t *ppos);
 225static int pt_detect(void);
 226
 227static int pt_identify (int unit);
 228
 229/* bits in PT.flags */
 230
 231#define PT_MEDIA        1
 232#define PT_WRITE_OK     2
 233#define PT_REWIND       4
 234#define PT_WRITING      8
 235#define PT_READING     16
 236#define PT_EOF         32
 237
 238#define PT_NAMELEN      8
 239#define PT_BUFSIZE  16384
 240
 241struct pt_unit {
 242        struct pi_adapter pia;    /* interface to paride layer */
 243        struct pi_adapter *pi;
 244        int flags;                /* various state flags */
 245        int last_sense;           /* result of last request sense */
 246        int drive;                /* drive */
 247        int access;               /* count of active opens ... */
 248        int bs;                   /* block size */
 249        int capacity;             /* Size of tape in KB */
 250        int present;              /* device present ? */
 251        char *bufptr;
 252        char name[PT_NAMELEN];    /* pf0, pf1, ... */
 253        };
 254
 255struct pt_unit pt[PT_UNITS];
 256
 257/*  'unit' must be defined in all functions - either as a local or a param */
 258
 259#define PT pt[unit]
 260#define PI PT.pi
 261
 262static char pt_scratch[512];            /* scratch block buffer */
 263
 264/* kernel glue structures */
 265
 266static struct file_operations pt_fops = {
 267        owner:          THIS_MODULE,
 268        read:           pt_read,
 269        write:          pt_write,
 270        ioctl:          pt_ioctl,
 271        open:           pt_open,
 272        release:        pt_release,
 273};
 274
 275void pt_init_units( void )
 276
 277{       int     unit, j;
 278
 279        pt_drive_count = 0;
 280        for (unit=0;unit<PT_UNITS;unit++) {
 281                PT.pi = & PT.pia;
 282                PT.access = 0;
 283                PT.flags = 0;
 284                PT.last_sense = 0;
 285                PT.present = 0;
 286                PT.bufptr = NULL;
 287                PT.drive = DU[D_SLV];
 288                j = 0;
 289                while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
 290                PT.name[j++] = '0' + unit;
 291                PT.name[j] = 0;
 292                if (DU[D_PRT]) pt_drive_count++;
 293        }
 294} 
 295
 296static devfs_handle_t devfs_handle;
 297
 298int pt_init (void)      /* preliminary initialisation */
 299
 300{       int unit;
 301
 302        if (disable) return -1;
 303
 304        pt_init_units();
 305
 306        if (pt_detect()) return -1;
 307
 308        if (devfs_register_chrdev(major,name,&pt_fops)) {
 309                printk("pt_init: unable to get major number %d\n",
 310                        major);
 311                for (unit=0;unit<PT_UNITS;unit++)
 312                  if (PT.present) pi_release(PI);
 313                return -1;
 314        }
 315
 316        devfs_handle = devfs_mk_dir (NULL, "pt", NULL);
 317        devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT,
 318                               major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
 319                               &pt_fops, NULL);
 320        devfs_register_series (devfs_handle, "%un", 4, DEVFS_FL_DEFAULT,
 321                               major, 128, S_IFCHR | S_IRUSR | S_IWUSR,
 322                               &pt_fops, NULL);
 323        return 0;
 324}
 325
 326#ifdef MODULE
 327
 328/* Glue for modules ... */
 329
 330void    cleanup_module(void);
 331
 332int     init_module(void)
 333
 334{       int     err;
 335
 336#ifdef PARIDE_JUMBO
 337       { extern paride_init();
 338         paride_init();
 339       } 
 340#endif
 341
 342        err = pt_init();
 343
 344        return err;
 345}
 346
 347void    cleanup_module(void)
 348
 349{       int unit;
 350
 351        devfs_unregister (devfs_handle);
 352        devfs_unregister_chrdev(major,name);
 353
 354        for (unit=0;unit<PT_UNITS;unit++)
 355          if (PT.present) pi_release(PI);
 356}
 357
 358#endif
 359
 360#define WR(c,r,v)       pi_write_regr(PI,c,r,v)
 361#define RR(c,r)         (pi_read_regr(PI,c,r))
 362
 363#define DRIVE           (0xa0+0x10*PT.drive)
 364
 365static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
 366
 367{       int j, r, e, s, p;
 368
 369        j = 0;
 370        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
 371                udelay(PT_SPIN_DEL);
 372
 373        if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
 374           s = RR(0,7);
 375           e = RR(0,1);
 376           p = RR(0,2);
 377           if (j >= PT_SPIN) e |= 0x100;
 378           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
 379                           " loop=%d phase=%d\n",
 380                            PT.name,fun,msg,r,s,e,j,p);
 381           return (e<<8)+s;
 382        }
 383        return 0;
 384}
 385
 386static int pt_command( int unit, char * cmd, int dlen, char * fun )
 387
 388{       pi_connect(PI);
 389
 390        WR(0,6,DRIVE);
 391
 392        if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
 393                pi_disconnect(PI);
 394                return -1;
 395        }
 396
 397        WR(0,4,dlen % 256);
 398        WR(0,5,dlen / 256);
 399        WR(0,7,0xa0);          /* ATAPI packet command */
 400
 401        if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
 402                pi_disconnect(PI);
 403                return -1;
 404        }
 405
 406        if (RR(0,2) != 1) {
 407           printk("%s: %s: command phase error\n",PT.name,fun);
 408           pi_disconnect(PI);
 409           return -1;
 410        }
 411
 412        pi_write_block(PI,cmd,12);
 413
 414        return 0;
 415}
 416
 417static int pt_completion( int unit, char * buf, char * fun )
 418
 419{       int r, s, n, p;
 420
 421        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
 422                        fun,"completion");
 423
 424        if (RR(0,7)&STAT_DRQ) { 
 425           n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
 426           p = RR(0,2)&3;
 427           if (p == 0) pi_write_block(PI,buf,n);
 428           if (p == 2) pi_read_block(PI,buf,n);
 429        }
 430
 431        s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
 432
 433        pi_disconnect(PI); 
 434
 435        return (r?r:s);
 436}
 437
 438static void pt_req_sense( int unit, int quiet )
 439
 440{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
 441        char    buf[16];
 442        int     r;
 443
 444        r = pt_command(unit,rs_cmd,16,"Request sense");
 445        mdelay(1);
 446        if (!r) pt_completion(unit,buf,"Request sense");
 447
 448        PT.last_sense = -1;
 449        if (!r) {
 450            if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
 451                                    PT.name,buf[2]&0xf,buf[12],buf[13]);
 452            PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
 453                                         | ((buf[13]&0xff)<<16) ;
 454        } 
 455}
 456
 457static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
 458
 459{       int r;
 460
 461        r = pt_command(unit,cmd,dlen,fun);
 462        mdelay(1);
 463        if (!r) r = pt_completion(unit,buf,fun);
 464        if (r) pt_req_sense(unit,!fun);
 465        
 466        return r;
 467}
 468
 469static void pt_sleep( int cs )
 470
 471{       current->state = TASK_INTERRUPTIBLE;
 472        schedule_timeout(cs);
 473}
 474
 475static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
 476
 477{       int     k, e, s;
 478
 479        k = 0; e = 0; s = 0;
 480        while (k < tmo) {
 481                pt_sleep(pause);
 482                k++;
 483                pi_connect(PI);
 484                WR(0,6,DRIVE);
 485                s = RR(0,7);
 486                e = RR(0,1);
 487                pi_disconnect(PI);
 488                if (s & (STAT_ERR|STAT_SEEK)) break;
 489        }
 490        if ((k >= tmo) || (s & STAT_ERR)) {
 491           if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
 492             else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
 493           pt_req_sense(unit,0);
 494           return 0;
 495        }
 496        return 1;
 497}
 498
 499static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
 500
 501{       if (pt_command(unit,cmd,0,fun)) {
 502                pt_req_sense(unit,0);
 503                return;
 504        }
 505        pi_disconnect(PI);
 506        pt_poll_dsc(unit,HZ,tmo,fun);
 507}
 508
 509static void pt_rewind( int unit )
 510
 511{       char    rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
 512
 513        pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
 514}
 515
 516static void pt_write_fm( int unit )
 517
 518{       char    wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
 519
 520        pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
 521}
 522
 523#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 524
 525static int pt_reset( int unit )
 526
 527{       int     i, k, flg;
 528        int     expect[5] = {1,1,1,0x14,0xeb};
 529
 530        pi_connect(PI);
 531        WR(0,6,DRIVE);
 532        WR(0,7,8);
 533
 534        pt_sleep(20*HZ/1000);
 535
 536        k = 0;
 537        while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
 538                pt_sleep(HZ/10);
 539
 540        flg = 1;
 541        for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
 542
 543        if (verbose) {
 544                printk("%s: Reset (%d) signature = ",PT.name,k);
 545                for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
 546                if (!flg) printk(" (incorrect)");
 547                printk("\n");
 548        }
 549        
 550        pi_disconnect(PI);
 551        return flg-1;   
 552}
 553
 554static int pt_ready_wait( int unit, int tmo )
 555
 556{       char    tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
 557        int     k, p;
 558
 559        k = 0;
 560        while (k < tmo) {
 561          PT.last_sense = 0;
 562          pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
 563          p = PT.last_sense;
 564          if (!p) return 0;
 565          if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
 566          k++;
 567          pt_sleep(HZ);
 568        }
 569        return 0x000020;        /* timeout */
 570}
 571
 572static void xs( char *buf, char *targ, int offs, int len )
 573
 574{       int     j,k,l;
 575
 576        j=0; l=0;
 577        for (k=0;k<len;k++) 
 578           if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
 579                l=targ[j++]=buf[k+offs];
 580        if (l==0x20) j--;
 581        targ[j]=0;
 582}
 583
 584static int xn( char *buf, int offs, int size )
 585
 586{       int     v,k;
 587
 588        v=0; 
 589        for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
 590        return v;
 591}
 592
 593static int pt_identify( int unit )
 594
 595{       int     dt, s;
 596        char    *ms[2] = {"master","slave"};
 597        char    mf[10], id[18];
 598        char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
 599        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
 600        char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
 601        char    buf[36];
 602
 603        s = pt_atapi(unit,id_cmd,36,buf,"identify");
 604        if (s) return -1;
 605
 606        dt = buf[0] & 0x1f;
 607        if (dt != 1) {
 608                if (verbose) 
 609                   printk("%s: Drive %d, unsupported type %d\n",
 610                                PT.name,PT.drive,dt);
 611                return -1;
 612        }
 613
 614        xs(buf,mf,8,8);
 615        xs(buf,id,16,16);
 616
 617        PT.flags = 0;
 618        PT.capacity = 0;
 619        PT.bs = 0;
 620
 621        if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
 622
 623        if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
 624          if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
 625          PT.bs = xn(buf,10,2);
 626        }
 627
 628        if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) 
 629                PT.capacity = xn(buf,24,4);
 630
 631        printk("%s: %s %s, %s",
 632                PT.name,mf,id,ms[PT.drive]);
 633        if (!(PT.flags & PT_MEDIA)) 
 634                printk(", no media\n");
 635        else {  if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
 636                printk(", blocksize %d, %d MB\n",
 637                       PT.bs,PT.capacity/1024);
 638        }
 639
 640        return 0;
 641}
 642
 643static int pt_probe( int unit )
 644
 645/*      returns  0, with id set if drive is detected
 646                -1, if drive detection failed
 647*/
 648
 649{       if (PT.drive == -1) {
 650           for (PT.drive=0;PT.drive<=1;PT.drive++)
 651                if (!pt_reset(unit)) return pt_identify(unit);
 652        } else {
 653           if (!pt_reset(unit)) return pt_identify(unit);
 654        }
 655        return -1; 
 656}
 657
 658static int pt_detect( void )
 659
 660{       int     k, unit;
 661
 662        printk("%s: %s version %s, major %d\n",
 663                name,name,PT_VERSION,major);
 664
 665        k = 0;
 666        if (pt_drive_count == 0) {
 667            unit = 0;
 668            if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
 669                        PI_PT,verbose,PT.name)) {
 670                if (!pt_probe(unit)) {
 671                        PT.present = 1;
 672                        k++;
 673                } else pi_release(PI);
 674            }
 675
 676        } else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
 677            if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
 678                        DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
 679                        PT.name)) { 
 680                if (!pt_probe(unit)) {
 681                        PT.present = 1;
 682                        k++;
 683                } else pi_release(PI);
 684            }
 685
 686        if (k) return 0;
 687
 688        printk("%s: No ATAPI tape drive detected\n",name);
 689        return -1;
 690}
 691
 692#define DEVICE_NR(dev)  (MINOR(dev) % 128)
 693
 694static int pt_open (struct inode *inode, struct file *file)
 695
 696{       int     unit = DEVICE_NR(inode->i_rdev);
 697
 698        if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
 699
 700        PT.access++;
 701
 702        if (PT.access > 1) {
 703                PT.access--;
 704                return -EBUSY;
 705        }
 706
 707        pt_identify(unit);
 708
 709        if (!PT.flags & PT_MEDIA) {
 710                PT.access--;
 711                return -ENODEV;
 712                }
 713
 714        if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
 715                PT.access--;
 716                return -EROFS;
 717                }
 718
 719        if (!(MINOR(inode->i_rdev) & 128))
 720                PT.flags |= PT_REWIND;
 721
 722        PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
 723        if (PT.bufptr == NULL) {
 724                PT.access--;
 725                printk("%s: buffer allocation failed\n",PT.name);
 726                return -ENOMEM;
 727        }
 728
 729        return 0;
 730}
 731
 732static int pt_ioctl(struct inode *inode,struct file *file,
 733                    unsigned int cmd, unsigned long arg)
 734{
 735        int unit;
 736        struct mtop mtop;
 737
 738        if (!inode || !inode->i_rdev)
 739                return -EINVAL;
 740        unit = DEVICE_NR(inode->i_rdev);
 741        if (unit >= PT_UNITS)
 742                return -EINVAL;
 743        if (!PT.present)
 744                return -ENODEV;
 745
 746        switch (cmd) {
 747            case MTIOCTOP:      
 748                if (copy_from_user((char *)&mtop, (char *)arg, 
 749                                   sizeof(struct mtop))) return -EFAULT;
 750
 751                switch (mtop.mt_op) {
 752
 753                    case MTREW: 
 754                        pt_rewind(unit);
 755                        return 0;
 756
 757                    case MTWEOF:
 758                        pt_write_fm(unit);
 759                        return 0;
 760
 761                    default:    
 762                        printk("%s: Unimplemented mt_op %d\n",PT.name,
 763                                        mtop.mt_op);
 764                        return -EINVAL;
 765                }
 766
 767            default:
 768                printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
 769                return -EINVAL;
 770
 771        }
 772}
 773
 774
 775static int pt_release (struct inode *inode, struct file *file)
 776{
 777        int     unit = DEVICE_NR(inode->i_rdev);
 778
 779        if ((unit >= PT_UNITS) || (PT.access <= 0)) 
 780                return -EINVAL;
 781
 782        lock_kernel();
 783        if (PT.flags & PT_WRITING) pt_write_fm(unit);
 784
 785        if (PT.flags & PT_REWIND) pt_rewind(unit);      
 786
 787        PT.access--;
 788
 789        kfree(PT.bufptr);
 790        PT.bufptr = NULL;
 791        unlock_kernel();
 792
 793        return 0;
 794
 795}
 796
 797static ssize_t pt_read(struct file * filp, char * buf, 
 798                       size_t count, loff_t *ppos)
 799{
 800        struct  inode *ino = filp->f_dentry->d_inode;
 801        int     unit = DEVICE_NR(ino->i_rdev);
 802        char    rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
 803        int     k, n, r, p, s, t, b;
 804
 805        if (!(PT.flags & (PT_READING|PT_WRITING))) {
 806            PT.flags |= PT_READING;
 807            if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
 808                        return -EIO;
 809        } else if (PT.flags & PT_WRITING) return -EIO;
 810
 811        if (PT.flags & PT_EOF) return 0;
 812
 813        t = 0;
 814
 815        while (count > 0) {
 816
 817            if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO;
 818
 819            n = count;
 820            if (n > 32768) n = 32768;   /* max per command */
 821            b = (n-1+PT.bs)/PT.bs;
 822            n = b*PT.bs;                /* rounded up to even block */
 823
 824            rd_cmd[4] = b;
 825
 826            r = pt_command(unit,rd_cmd,n,"read");
 827
 828            mdelay(1);
 829
 830            if (r) {
 831                pt_req_sense(unit,0);
 832                return -EIO;
 833            }
 834
 835            while (1) {
 836
 837                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
 838                                           DBMSG("read DRQ"),"");
 839
 840                if (r & STAT_SENSE) {
 841                    pi_disconnect(PI);
 842                    pt_req_sense(unit,0);
 843                    return -EIO;
 844                }
 845
 846                if (r) PT.flags |= PT_EOF; 
 847
 848                s = RR(0,7);
 849
 850                if (!(s & STAT_DRQ)) break;
 851
 852                n = (RR(0,4)+256*RR(0,5));
 853                p = (RR(0,2)&3);
 854                if (p != 2) {
 855                    pi_disconnect(PI);
 856                    printk("%s: Phase error on read: %d\n",PT.name,p);
 857                    return -EIO;
 858                }
 859
 860                while (n > 0) {
 861                    k = n;
 862                    if (k > PT_BUFSIZE) k = PT_BUFSIZE; 
 863                    pi_read_block(PI,PT.bufptr,k);
 864                    n -= k;
 865                    b = k;
 866                    if (b > count) b = count;
 867                    if (copy_to_user(buf + t, PT.bufptr, b)) {
 868                        pi_disconnect(PI);
 869                        return -EFAULT;
 870                    }
 871                    t += b;
 872                    count -= b;
 873                }
 874
 875            }
 876            pi_disconnect(PI);
 877            if (PT.flags & PT_EOF) break;
 878        }
 879
 880        return t;
 881
 882}
 883
 884static ssize_t pt_write(struct file * filp, const char * buf, 
 885                        size_t count, loff_t *ppos)
 886{
 887        struct inode *ino = filp->f_dentry->d_inode;
 888        int unit = DEVICE_NR(ino->i_rdev);
 889        char    wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
 890        int     k, n, r, p, s, t, b;
 891
 892        if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
 893
 894        if (!(PT.flags & (PT_READING|PT_WRITING))) {
 895            PT.flags |= PT_WRITING;
 896            if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
 897                        return -EIO;
 898        } else if (PT.flags&PT_READING) return -EIO;
 899
 900        if (PT.flags & PT_EOF) return -ENOSPC;
 901
 902        t = 0;
 903
 904        while (count > 0) {
 905
 906            if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO;
 907
 908            n = count;
 909            if (n > 32768) n = 32768;   /* max per command */
 910            b = (n-1+PT.bs)/PT.bs;
 911            n = b*PT.bs;                /* rounded up to even block */
 912
 913            wr_cmd[4] = b;
 914
 915            r = pt_command(unit,wr_cmd,n,"write");
 916
 917            mdelay(1);
 918
 919            if (r) {                    /* error delivering command only */
 920                pt_req_sense(unit,0);
 921                return -EIO;
 922            }
 923
 924            while (1) {
 925
 926                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
 927                                                DBMSG("write DRQ"),NULL);
 928
 929                if (r & STAT_SENSE) {
 930                    pi_disconnect(PI);
 931                    pt_req_sense(unit,0);
 932                    return -EIO;
 933                }
 934
 935                if (r) PT.flags |= PT_EOF;
 936
 937                s = RR(0,7);
 938
 939                if (!(s & STAT_DRQ)) break;
 940
 941                n = (RR(0,4)+256*RR(0,5));
 942                p = (RR(0,2)&3);
 943                if (p != 0) {
 944                    pi_disconnect(PI);
 945                    printk("%s: Phase error on write: %d \n",PT.name,p);
 946                    return -EIO;
 947                }
 948
 949                while (n > 0) {
 950                    k = n;
 951                    if (k > PT_BUFSIZE) k = PT_BUFSIZE;
 952                    b = k;
 953                    if (b > count) b = count;
 954                    if (copy_from_user(PT.bufptr, buf + t, b)) {
 955                        pi_disconnect(PI);
 956                        return -EFAULT;
 957                    }
 958                    pi_write_block(PI,PT.bufptr,k);
 959                    t += b;
 960                    count -= b;
 961                    n -= k;
 962                }
 963
 964            }
 965            pi_disconnect(PI);
 966            if (PT.flags & PT_EOF) break;
 967        }
 968
 969        return t;
 970}
 971
 972/* end of pt.c */
 973
 974MODULE_LICENSE("GPL");
 975
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.