linux/drivers/block/paride/pcd.c
<<
>>
Prefs
   1/* 
   2        pcd.c   (c) 1997-8  Grant R. Guenther <grant@torque.net>
   3                            Under the terms of the GNU General Public License.
   4
   5        This is a high-level driver for parallel port ATAPI CD-ROM
   6        drives based on chips supported by the paride module.
   7
   8        By default, the driver will autoprobe for a single parallel
   9        port ATAPI CD-ROM drive, but if their individual parameters are
  10        specified, the driver can handle up to 4 drives.
  11
  12        The behaviour of the pcd driver can be altered by setting
  13        some parameters from the insmod command line.  The following
  14        parameters are adjustable:
  15
  16            drive0      These four arguments can be arrays of       
  17            drive1      1-6 integers as follows:
  18            drive2
  19            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
  20
  21                        Where,
  22
  23                <prt>   is the base of the parallel port address for
  24                        the corresponding drive.  (required)
  25
  26                <pro>   is the protocol number for the adapter that
  27                        supports this drive.  These numbers are
  28                        logged by 'paride' when the protocol modules
  29                        are initialised.  (0 if not given)
  30
  31                <uni>   for those adapters that support chained
  32                        devices, this is the unit selector for the
  33                        chain of devices on the given port.  It should
  34                        be zero for devices that don't support chaining.
  35                        (0 if not given)
  36
  37                <mod>   this can be -1 to choose the best mode, or one
  38                        of the mode numbers supported by the adapter.
  39                        (-1 if not given)
  40
  41                <slv>   ATAPI CD-ROMs can be jumpered to master or slave.
  42                        Set this to 0 to choose the master drive, 1 to
  43                        choose the slave, -1 (the default) to choose the
  44                        first drive found.
  45
  46                <dly>   some parallel ports require the driver to 
  47                        go more slowly.  -1 sets a default value that
  48                        should work with the chosen protocol.  Otherwise,
  49                        set this to a small integer, the larger it is
  50                        the slower the port i/o.  In some cases, setting
  51                        this to zero will speed up the device. (default -1)
  52                        
  53            major       You may use this parameter to override the
  54                        default major number (46) that this driver
  55                        will use.  Be sure to change the device
  56                        name as well.
  57
  58            name        This parameter is a character string that
  59                        contains the name the kernel will use for this
  60                        device (in /proc output, for instance).
  61                        (default "pcd")
  62
  63            verbose     This parameter controls the amount of logging
  64                        that the driver will do.  Set it to 0 for
  65                        normal operation, 1 to see autoprobe progress
  66                        messages, or 2 to see additional debugging
  67                        output.  (default 0)
  68  
  69            nice        This parameter controls the driver's use of
  70                        idle CPU time, at the expense of some speed.
  71 
  72        If this driver is built into the kernel, you can use the
  73        following kernel command line parameters, with the same values
  74        as the corresponding module parameters listed above:
  75
  76            pcd.drive0
  77            pcd.drive1
  78            pcd.drive2
  79            pcd.drive3
  80            pcd.nice
  81
  82        In addition, you can use the parameter pcd.disable to disable
  83        the driver entirely.
  84
  85*/
  86
  87/* Changes:
  88
  89        1.01    GRG 1998.01.24  Added test unit ready support
  90        1.02    GRG 1998.05.06  Changes to pcd_completion, ready_wait,
  91                                and loosen interpretation of ATAPI
  92                                standard for clearing error status.
  93                                Use spinlocks. Eliminate sti().
  94        1.03    GRG 1998.06.16  Eliminated an Ugh
  95        1.04    GRG 1998.08.15  Added extra debugging, improvements to
  96                                pcd_completion, use HZ in loop timing
  97        1.05    GRG 1998.08.16  Conformed to "Uniform CD-ROM" standard
  98        1.06    GRG 1998.08.19  Added audio ioctl support
  99        1.07    GRG 1998.09.24  Increased reset timeout, added jumbo support
 100
 101*/
 102
 103#define PCD_VERSION     "1.07"
 104#define PCD_MAJOR       46
 105#define PCD_NAME        "pcd"
 106#define PCD_UNITS       4
 107
 108/* Here are things one can override from the insmod command.
 109   Most are autoprobed by paride unless set here.  Verbose is off
 110   by default.
 111
 112*/
 113
 114static int verbose = 0;
 115static int major = PCD_MAJOR;
 116static char *name = PCD_NAME;
 117static int nice = 0;
 118static int disable = 0;
 119
 120static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
 121static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
 122static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
 123static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
 124
 125static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 126static int pcd_drive_count;
 127
 128enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 129
 130/* end of parameters */
 131
 132#include <linux/module.h>
 133#include <linux/init.h>
 134#include <linux/errno.h>
 135#include <linux/fs.h>
 136#include <linux/kernel.h>
 137#include <linux/delay.h>
 138#include <linux/cdrom.h>
 139#include <linux/spinlock.h>
 140#include <linux/blkdev.h>
 141#include <linux/mutex.h>
 142#include <linux/uaccess.h>
 143
 144static DEFINE_MUTEX(pcd_mutex);
 145static DEFINE_SPINLOCK(pcd_lock);
 146
 147module_param(verbose, int, 0644);
 148module_param(major, int, 0);
 149module_param(name, charp, 0);
 150module_param(nice, int, 0);
 151module_param_array(drive0, int, NULL, 0);
 152module_param_array(drive1, int, NULL, 0);
 153module_param_array(drive2, int, NULL, 0);
 154module_param_array(drive3, int, NULL, 0);
 155
 156#include "paride.h"
 157#include "pseudo.h"
 158
 159#define PCD_RETRIES          5
 160#define PCD_TMO            800  /* timeout in jiffies */
 161#define PCD_DELAY           50  /* spin delay in uS */
 162#define PCD_READY_TMO       20  /* in seconds */
 163#define PCD_RESET_TMO      100  /* in tenths of a second */
 164
 165#define PCD_SPIN        (1000000*PCD_TMO)/(HZ*PCD_DELAY)
 166
 167#define IDE_ERR         0x01
 168#define IDE_DRQ         0x08
 169#define IDE_READY       0x40
 170#define IDE_BUSY        0x80
 171
 172static int pcd_open(struct cdrom_device_info *cdi, int purpose);
 173static void pcd_release(struct cdrom_device_info *cdi);
 174static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
 175static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
 176                                     unsigned int clearing, int slot_nr);
 177static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
 178static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
 179static int pcd_drive_reset(struct cdrom_device_info *cdi);
 180static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
 181static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
 182                           unsigned int cmd, void *arg);
 183static int pcd_packet(struct cdrom_device_info *cdi,
 184                      struct packet_command *cgc);
 185
 186static int pcd_detect(void);
 187static void pcd_probe_capabilities(void);
 188static void do_pcd_read_drq(void);
 189static void do_pcd_request(struct request_queue * q);
 190static void do_pcd_read(void);
 191
 192struct pcd_unit {
 193        struct pi_adapter pia;  /* interface to paride layer */
 194        struct pi_adapter *pi;
 195        int drive;              /* master/slave */
 196        int last_sense;         /* result of last request sense */
 197        int changed;            /* media change seen */
 198        int present;            /* does this unit exist ? */
 199        char *name;             /* pcd0, pcd1, etc */
 200        struct cdrom_device_info info;  /* uniform cdrom interface */
 201        struct gendisk *disk;
 202};
 203
 204static struct pcd_unit pcd[PCD_UNITS];
 205
 206static char pcd_scratch[64];
 207static char pcd_buffer[2048];   /* raw block buffer */
 208static int pcd_bufblk = -1;     /* block in buffer, in CD units,
 209                                   -1 for nothing there. See also
 210                                   pd_unit.
 211                                 */
 212
 213/* the variables below are used mainly in the I/O request engine, which
 214   processes only one request at a time.
 215*/
 216
 217static struct pcd_unit *pcd_current; /* current request's drive */
 218static struct request *pcd_req;
 219static int pcd_retries;         /* retries on current request */
 220static int pcd_busy;            /* request being processed ? */
 221static int pcd_sector;          /* address of next requested sector */
 222static int pcd_count;           /* number of blocks still to do */
 223static char *pcd_buf;           /* buffer for request in progress */
 224static void *par_drv;           /* reference of parport driver */
 225
 226/* kernel glue structures */
 227
 228static int pcd_block_open(struct block_device *bdev, fmode_t mode)
 229{
 230        struct pcd_unit *cd = bdev->bd_disk->private_data;
 231        int ret;
 232
 233        check_disk_change(bdev);
 234
 235        mutex_lock(&pcd_mutex);
 236        ret = cdrom_open(&cd->info, bdev, mode);
 237        mutex_unlock(&pcd_mutex);
 238
 239        return ret;
 240}
 241
 242static void pcd_block_release(struct gendisk *disk, fmode_t mode)
 243{
 244        struct pcd_unit *cd = disk->private_data;
 245        mutex_lock(&pcd_mutex);
 246        cdrom_release(&cd->info, mode);
 247        mutex_unlock(&pcd_mutex);
 248}
 249
 250static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
 251                                unsigned cmd, unsigned long arg)
 252{
 253        struct pcd_unit *cd = bdev->bd_disk->private_data;
 254        int ret;
 255
 256        mutex_lock(&pcd_mutex);
 257        ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
 258        mutex_unlock(&pcd_mutex);
 259
 260        return ret;
 261}
 262
 263static unsigned int pcd_block_check_events(struct gendisk *disk,
 264                                           unsigned int clearing)
 265{
 266        struct pcd_unit *cd = disk->private_data;
 267        return cdrom_check_events(&cd->info, clearing);
 268}
 269
 270static const struct block_device_operations pcd_bdops = {
 271        .owner          = THIS_MODULE,
 272        .open           = pcd_block_open,
 273        .release        = pcd_block_release,
 274        .ioctl          = pcd_block_ioctl,
 275        .check_events   = pcd_block_check_events,
 276};
 277
 278static const struct cdrom_device_ops pcd_dops = {
 279        .open           = pcd_open,
 280        .release        = pcd_release,
 281        .drive_status   = pcd_drive_status,
 282        .check_events   = pcd_check_events,
 283        .tray_move      = pcd_tray_move,
 284        .lock_door      = pcd_lock_door,
 285        .get_mcn        = pcd_get_mcn,
 286        .reset          = pcd_drive_reset,
 287        .audio_ioctl    = pcd_audio_ioctl,
 288        .generic_packet = pcd_packet,
 289        .capability     = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
 290                          CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
 291                          CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
 292                          CDC_CD_RW,
 293};
 294
 295static void pcd_init_units(void)
 296{
 297        struct pcd_unit *cd;
 298        int unit;
 299
 300        pcd_drive_count = 0;
 301        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 302                struct gendisk *disk = alloc_disk(1);
 303                if (!disk)
 304                        continue;
 305                disk->queue = blk_init_queue(do_pcd_request, &pcd_lock);
 306                if (!disk->queue) {
 307                        put_disk(disk);
 308                        continue;
 309                }
 310                blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
 311                cd->disk = disk;
 312                cd->pi = &cd->pia;
 313                cd->present = 0;
 314                cd->last_sense = 0;
 315                cd->changed = 1;
 316                cd->drive = (*drives[unit])[D_SLV];
 317                if ((*drives[unit])[D_PRT])
 318                        pcd_drive_count++;
 319
 320                cd->name = &cd->info.name[0];
 321                snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
 322                cd->info.ops = &pcd_dops;
 323                cd->info.handle = cd;
 324                cd->info.speed = 0;
 325                cd->info.capacity = 1;
 326                cd->info.mask = 0;
 327                disk->major = major;
 328                disk->first_minor = unit;
 329                strcpy(disk->disk_name, cd->name);      /* umm... */
 330                disk->fops = &pcd_bdops;
 331                disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
 332        }
 333}
 334
 335static int pcd_open(struct cdrom_device_info *cdi, int purpose)
 336{
 337        struct pcd_unit *cd = cdi->handle;
 338        if (!cd->present)
 339                return -ENODEV;
 340        return 0;
 341}
 342
 343static void pcd_release(struct cdrom_device_info *cdi)
 344{
 345}
 346
 347static inline int status_reg(struct pcd_unit *cd)
 348{
 349        return pi_read_regr(cd->pi, 1, 6);
 350}
 351
 352static inline int read_reg(struct pcd_unit *cd, int reg)
 353{
 354        return pi_read_regr(cd->pi, 0, reg);
 355}
 356
 357static inline void write_reg(struct pcd_unit *cd, int reg, int val)
 358{
 359        pi_write_regr(cd->pi, 0, reg, val);
 360}
 361
 362static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
 363{
 364        int j, r, e, s, p;
 365
 366        j = 0;
 367        while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
 368               && (j++ < PCD_SPIN))
 369                udelay(PCD_DELAY);
 370
 371        if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
 372                s = read_reg(cd, 7);
 373                e = read_reg(cd, 1);
 374                p = read_reg(cd, 2);
 375                if (j > PCD_SPIN)
 376                        e |= 0x100;
 377                if (fun)
 378                        printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
 379                               " loop=%d phase=%d\n",
 380                               cd->name, fun, msg, r, s, e, j, p);
 381                return (s << 8) + r;
 382        }
 383        return 0;
 384}
 385
 386static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
 387{
 388        pi_connect(cd->pi);
 389
 390        write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
 391
 392        if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
 393                pi_disconnect(cd->pi);
 394                return -1;
 395        }
 396
 397        write_reg(cd, 4, dlen % 256);
 398        write_reg(cd, 5, dlen / 256);
 399        write_reg(cd, 7, 0xa0); /* ATAPI packet command */
 400
 401        if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
 402                pi_disconnect(cd->pi);
 403                return -1;
 404        }
 405
 406        if (read_reg(cd, 2) != 1) {
 407                printk("%s: %s: command phase error\n", cd->name, fun);
 408                pi_disconnect(cd->pi);
 409                return -1;
 410        }
 411
 412        pi_write_block(cd->pi, cmd, 12);
 413
 414        return 0;
 415}
 416
 417static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
 418{
 419        int r, d, p, n, k, j;
 420
 421        r = -1;
 422        k = 0;
 423        j = 0;
 424
 425        if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
 426                      fun, "completion")) {
 427                r = 0;
 428                while (read_reg(cd, 7) & IDE_DRQ) {
 429                        d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
 430                        n = (d + 3) & 0xfffc;
 431                        p = read_reg(cd, 2) & 3;
 432
 433                        if ((p == 2) && (n > 0) && (j == 0)) {
 434                                pi_read_block(cd->pi, buf, n);
 435                                if (verbose > 1)
 436                                        printk("%s: %s: Read %d bytes\n",
 437                                               cd->name, fun, n);
 438                                r = 0;
 439                                j++;
 440                        } else {
 441                                if (verbose > 1)
 442                                        printk
 443                                            ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
 444                                             cd->name, fun, p, d, k);
 445                                if (verbose < 2)
 446                                        printk_once(
 447                                            "%s: WARNING: ATAPI phase errors\n",
 448                                            cd->name);
 449                                mdelay(1);
 450                        }
 451                        if (k++ > PCD_TMO) {
 452                                printk("%s: Stuck DRQ\n", cd->name);
 453                                break;
 454                        }
 455                        if (pcd_wait
 456                            (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
 457                             "completion")) {
 458                                r = -1;
 459                                break;
 460                        }
 461                }
 462        }
 463
 464        pi_disconnect(cd->pi);
 465
 466        return r;
 467}
 468
 469static void pcd_req_sense(struct pcd_unit *cd, char *fun)
 470{
 471        char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
 472        char buf[16];
 473        int r, c;
 474
 475        r = pcd_command(cd, rs_cmd, 16, "Request sense");
 476        mdelay(1);
 477        if (!r)
 478                pcd_completion(cd, buf, "Request sense");
 479
 480        cd->last_sense = -1;
 481        c = 2;
 482        if (!r) {
 483                if (fun)
 484                        printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
 485                               cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
 486                c = buf[2] & 0xf;
 487                cd->last_sense =
 488                    c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
 489        }
 490        if ((c == 2) || (c == 6))
 491                cd->changed = 1;
 492}
 493
 494static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
 495{
 496        int r;
 497
 498        r = pcd_command(cd, cmd, dlen, fun);
 499        mdelay(1);
 500        if (!r)
 501                r = pcd_completion(cd, buf, fun);
 502        if (r)
 503                pcd_req_sense(cd, fun);
 504
 505        return r;
 506}
 507
 508static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
 509{
 510        return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
 511                         "generic packet");
 512}
 513
 514#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 515
 516static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
 517                                     unsigned int clearing, int slot_nr)
 518{
 519        struct pcd_unit *cd = cdi->handle;
 520        int res = cd->changed;
 521        if (res)
 522                cd->changed = 0;
 523        return res ? DISK_EVENT_MEDIA_CHANGE : 0;
 524}
 525
 526static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
 527{
 528        char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
 529
 530        return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
 531                         lock ? "lock door" : "unlock door");
 532}
 533
 534static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
 535{
 536        char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
 537
 538        return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
 539                         position ? "eject" : "close tray");
 540}
 541
 542static void pcd_sleep(int cs)
 543{
 544        schedule_timeout_interruptible(cs);
 545}
 546
 547static int pcd_reset(struct pcd_unit *cd)
 548{
 549        int i, k, flg;
 550        int expect[5] = { 1, 1, 1, 0x14, 0xeb };
 551
 552        pi_connect(cd->pi);
 553        write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
 554        write_reg(cd, 7, 8);
 555
 556        pcd_sleep(20 * HZ / 1000);      /* delay a bit */
 557
 558        k = 0;
 559        while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
 560                pcd_sleep(HZ / 10);
 561
 562        flg = 1;
 563        for (i = 0; i < 5; i++)
 564                flg &= (read_reg(cd, i + 1) == expect[i]);
 565
 566        if (verbose) {
 567                printk("%s: Reset (%d) signature = ", cd->name, k);
 568                for (i = 0; i < 5; i++)
 569                        printk("%3x", read_reg(cd, i + 1));
 570                if (!flg)
 571                        printk(" (incorrect)");
 572                printk("\n");
 573        }
 574
 575        pi_disconnect(cd->pi);
 576        return flg - 1;
 577}
 578
 579static int pcd_drive_reset(struct cdrom_device_info *cdi)
 580{
 581        return pcd_reset(cdi->handle);
 582}
 583
 584static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
 585{
 586        char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 587        int k, p;
 588
 589        k = 0;
 590        while (k < tmo) {
 591                cd->last_sense = 0;
 592                pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
 593                p = cd->last_sense;
 594                if (!p)
 595                        return 0;
 596                if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
 597                        return p;
 598                k++;
 599                pcd_sleep(HZ);
 600        }
 601        return 0x000020;        /* timeout */
 602}
 603
 604static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
 605{
 606        char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 607        struct pcd_unit *cd = cdi->handle;
 608
 609        if (pcd_ready_wait(cd, PCD_READY_TMO))
 610                return CDS_DRIVE_NOT_READY;
 611        if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
 612                return CDS_NO_DISC;
 613        return CDS_DISC_OK;
 614}
 615
 616static int pcd_identify(struct pcd_unit *cd, char *id)
 617{
 618        int k, s;
 619        char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
 620
 621        pcd_bufblk = -1;
 622
 623        s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
 624
 625        if (s)
 626                return -1;
 627        if ((pcd_buffer[0] & 0x1f) != 5) {
 628                if (verbose)
 629                        printk("%s: %s is not a CD-ROM\n",
 630                               cd->name, cd->drive ? "Slave" : "Master");
 631                return -1;
 632        }
 633        memcpy(id, pcd_buffer + 16, 16);
 634        id[16] = 0;
 635        k = 16;
 636        while ((k >= 0) && (id[k] <= 0x20)) {
 637                id[k] = 0;
 638                k--;
 639        }
 640
 641        printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
 642
 643        return 0;
 644}
 645
 646/*
 647 * returns  0, with id set if drive is detected
 648 *          -1, if drive detection failed
 649 */
 650static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
 651{
 652        if (ms == -1) {
 653                for (cd->drive = 0; cd->drive <= 1; cd->drive++)
 654                        if (!pcd_reset(cd) && !pcd_identify(cd, id))
 655                                return 0;
 656        } else {
 657                cd->drive = ms;
 658                if (!pcd_reset(cd) && !pcd_identify(cd, id))
 659                        return 0;
 660        }
 661        return -1;
 662}
 663
 664static void pcd_probe_capabilities(void)
 665{
 666        int unit, r;
 667        char buffer[32];
 668        char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
 669        struct pcd_unit *cd;
 670
 671        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 672                if (!cd->present)
 673                        continue;
 674                r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
 675                if (r)
 676                        continue;
 677                /* we should now have the cap page */
 678                if ((buffer[11] & 1) == 0)
 679                        cd->info.mask |= CDC_CD_R;
 680                if ((buffer[11] & 2) == 0)
 681                        cd->info.mask |= CDC_CD_RW;
 682                if ((buffer[12] & 1) == 0)
 683                        cd->info.mask |= CDC_PLAY_AUDIO;
 684                if ((buffer[14] & 1) == 0)
 685                        cd->info.mask |= CDC_LOCK;
 686                if ((buffer[14] & 8) == 0)
 687                        cd->info.mask |= CDC_OPEN_TRAY;
 688                if ((buffer[14] >> 6) == 0)
 689                        cd->info.mask |= CDC_CLOSE_TRAY;
 690        }
 691}
 692
 693static int pcd_detect(void)
 694{
 695        char id[18];
 696        int k, unit;
 697        struct pcd_unit *cd;
 698
 699        printk("%s: %s version %s, major %d, nice %d\n",
 700               name, name, PCD_VERSION, major, nice);
 701
 702        par_drv = pi_register_driver(name);
 703        if (!par_drv) {
 704                pr_err("failed to register %s driver\n", name);
 705                return -1;
 706        }
 707
 708        k = 0;
 709        if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
 710                cd = pcd;
 711                if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
 712                            PI_PCD, verbose, cd->name)) {
 713                        if (!pcd_probe(cd, -1, id) && cd->disk) {
 714                                cd->present = 1;
 715                                k++;
 716                        } else
 717                                pi_release(cd->pi);
 718                }
 719        } else {
 720                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 721                        int *conf = *drives[unit];
 722                        if (!conf[D_PRT])
 723                                continue;
 724                        if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
 725                                     conf[D_UNI], conf[D_PRO], conf[D_DLY],
 726                                     pcd_buffer, PI_PCD, verbose, cd->name)) 
 727                                continue;
 728                        if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
 729                                cd->present = 1;
 730                                k++;
 731                        } else
 732                                pi_release(cd->pi);
 733                }
 734        }
 735        if (k)
 736                return 0;
 737
 738        printk("%s: No CD-ROM drive found\n", name);
 739        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 740                put_disk(cd->disk);
 741        pi_unregister_driver(par_drv);
 742        return -1;
 743}
 744
 745/* I/O request processing */
 746static int pcd_queue;
 747
 748static int set_next_request(void)
 749{
 750        struct pcd_unit *cd;
 751        struct request_queue *q;
 752        int old_pos = pcd_queue;
 753
 754        do {
 755                cd = &pcd[pcd_queue];
 756                q = cd->present ? cd->disk->queue : NULL;
 757                if (++pcd_queue == PCD_UNITS)
 758                        pcd_queue = 0;
 759                if (q) {
 760                        pcd_req = blk_fetch_request(q);
 761                        if (pcd_req)
 762                                break;
 763                }
 764        } while (pcd_queue != old_pos);
 765
 766        return pcd_req != NULL;
 767}
 768
 769static void pcd_request(void)
 770{
 771        if (pcd_busy)
 772                return;
 773        while (1) {
 774                if (!pcd_req && !set_next_request())
 775                        return;
 776
 777                if (rq_data_dir(pcd_req) == READ) {
 778                        struct pcd_unit *cd = pcd_req->rq_disk->private_data;
 779                        if (cd != pcd_current)
 780                                pcd_bufblk = -1;
 781                        pcd_current = cd;
 782                        pcd_sector = blk_rq_pos(pcd_req);
 783                        pcd_count = blk_rq_cur_sectors(pcd_req);
 784                        pcd_buf = bio_data(pcd_req->bio);
 785                        pcd_busy = 1;
 786                        ps_set_intr(do_pcd_read, NULL, 0, nice);
 787                        return;
 788                } else {
 789                        __blk_end_request_all(pcd_req, BLK_STS_IOERR);
 790                        pcd_req = NULL;
 791                }
 792        }
 793}
 794
 795static void do_pcd_request(struct request_queue *q)
 796{
 797        pcd_request();
 798}
 799
 800static inline void next_request(blk_status_t err)
 801{
 802        unsigned long saved_flags;
 803
 804        spin_lock_irqsave(&pcd_lock, saved_flags);
 805        if (!__blk_end_request_cur(pcd_req, err))
 806                pcd_req = NULL;
 807        pcd_busy = 0;
 808        pcd_request();
 809        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 810}
 811
 812static int pcd_ready(void)
 813{
 814        return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
 815}
 816
 817static void pcd_transfer(void)
 818{
 819
 820        while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
 821                int o = (pcd_sector % 4) * 512;
 822                memcpy(pcd_buf, pcd_buffer + o, 512);
 823                pcd_count--;
 824                pcd_buf += 512;
 825                pcd_sector++;
 826        }
 827}
 828
 829static void pcd_start(void)
 830{
 831        int b, i;
 832        char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
 833
 834        pcd_bufblk = pcd_sector / 4;
 835        b = pcd_bufblk;
 836        for (i = 0; i < 4; i++) {
 837                rd_cmd[5 - i] = b & 0xff;
 838                b = b >> 8;
 839        }
 840
 841        if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
 842                pcd_bufblk = -1;
 843                next_request(BLK_STS_IOERR);
 844                return;
 845        }
 846
 847        mdelay(1);
 848
 849        ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
 850}
 851
 852static void do_pcd_read(void)
 853{
 854        pcd_busy = 1;
 855        pcd_retries = 0;
 856        pcd_transfer();
 857        if (!pcd_count) {
 858                next_request(0);
 859                return;
 860        }
 861
 862        pi_do_claimed(pcd_current->pi, pcd_start);
 863}
 864
 865static void do_pcd_read_drq(void)
 866{
 867        unsigned long saved_flags;
 868
 869        if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
 870                if (pcd_retries < PCD_RETRIES) {
 871                        mdelay(1);
 872                        pcd_retries++;
 873                        pi_do_claimed(pcd_current->pi, pcd_start);
 874                        return;
 875                }
 876                pcd_bufblk = -1;
 877                next_request(BLK_STS_IOERR);
 878                return;
 879        }
 880
 881        do_pcd_read();
 882        spin_lock_irqsave(&pcd_lock, saved_flags);
 883        pcd_request();
 884        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 885}
 886
 887/* the audio_ioctl stuff is adapted from sr_ioctl.c */
 888
 889static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 890{
 891        struct pcd_unit *cd = cdi->handle;
 892
 893        switch (cmd) {
 894
 895        case CDROMREADTOCHDR:
 896
 897                {
 898                        char cmd[12] =
 899                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 900                         0, 0, 0 };
 901                        struct cdrom_tochdr *tochdr =
 902                            (struct cdrom_tochdr *) arg;
 903                        char buffer[32];
 904                        int r;
 905
 906                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
 907
 908                        tochdr->cdth_trk0 = buffer[2];
 909                        tochdr->cdth_trk1 = buffer[3];
 910
 911                        return r ? -EIO : 0;
 912                }
 913
 914        case CDROMREADTOCENTRY:
 915
 916                {
 917                        char cmd[12] =
 918                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 919                         0, 0, 0 };
 920
 921                        struct cdrom_tocentry *tocentry =
 922                            (struct cdrom_tocentry *) arg;
 923                        unsigned char buffer[32];
 924                        int r;
 925
 926                        cmd[1] =
 927                            (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
 928                        cmd[6] = tocentry->cdte_track;
 929
 930                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
 931
 932                        tocentry->cdte_ctrl = buffer[5] & 0xf;
 933                        tocentry->cdte_adr = buffer[5] >> 4;
 934                        tocentry->cdte_datamode =
 935                            (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
 936                        if (tocentry->cdte_format == CDROM_MSF) {
 937                                tocentry->cdte_addr.msf.minute = buffer[9];
 938                                tocentry->cdte_addr.msf.second = buffer[10];
 939                                tocentry->cdte_addr.msf.frame = buffer[11];
 940                        } else
 941                                tocentry->cdte_addr.lba =
 942                                    (((((buffer[8] << 8) + buffer[9]) << 8)
 943                                      + buffer[10]) << 8) + buffer[11];
 944
 945                        return r ? -EIO : 0;
 946                }
 947
 948        default:
 949
 950                return -ENOSYS;
 951        }
 952}
 953
 954static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 955{
 956        char cmd[12] =
 957            { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
 958        char buffer[32];
 959
 960        if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
 961                return -EIO;
 962
 963        memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 964        mcn->medium_catalog_number[13] = 0;
 965
 966        return 0;
 967}
 968
 969static int __init pcd_init(void)
 970{
 971        struct pcd_unit *cd;
 972        int unit;
 973
 974        if (disable)
 975                return -EINVAL;
 976
 977        pcd_init_units();
 978
 979        if (pcd_detect())
 980                return -ENODEV;
 981
 982        /* get the atapi capabilities page */
 983        pcd_probe_capabilities();
 984
 985        if (register_blkdev(major, name)) {
 986                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 987                        put_disk(cd->disk);
 988                return -EBUSY;
 989        }
 990
 991        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 992                if (cd->present) {
 993                        register_cdrom(&cd->info);
 994                        cd->disk->private_data = cd;
 995                        add_disk(cd->disk);
 996                }
 997        }
 998
 999        return 0;
1000}
1001
1002static void __exit pcd_exit(void)
1003{
1004        struct pcd_unit *cd;
1005        int unit;
1006
1007        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
1008                if (cd->present) {
1009                        del_gendisk(cd->disk);
1010                        pi_release(cd->pi);
1011                        unregister_cdrom(&cd->info);
1012                }
1013                blk_cleanup_queue(cd->disk->queue);
1014                put_disk(cd->disk);
1015        }
1016        unregister_blkdev(major, name);
1017        pi_unregister_driver(par_drv);
1018}
1019
1020MODULE_LICENSE("GPL");
1021module_init(pcd_init)
1022module_exit(pcd_exit)
1023