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 overide 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 kernel
  73        the following 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 <asm/uaccess.h>
 142
 143static DEFINE_SPINLOCK(pcd_lock);
 144
 145module_param(verbose, bool, 0644);
 146module_param(major, int, 0);
 147module_param(name, charp, 0);
 148module_param(nice, int, 0);
 149module_param_array(drive0, int, NULL, 0);
 150module_param_array(drive1, int, NULL, 0);
 151module_param_array(drive2, int, NULL, 0);
 152module_param_array(drive3, int, NULL, 0);
 153
 154#include "paride.h"
 155#include "pseudo.h"
 156
 157#define PCD_RETRIES          5
 158#define PCD_TMO            800  /* timeout in jiffies */
 159#define PCD_DELAY           50  /* spin delay in uS */
 160#define PCD_READY_TMO       20  /* in seconds */
 161#define PCD_RESET_TMO      100  /* in tenths of a second */
 162
 163#define PCD_SPIN        (1000000*PCD_TMO)/(HZ*PCD_DELAY)
 164
 165#define IDE_ERR         0x01
 166#define IDE_DRQ         0x08
 167#define IDE_READY       0x40
 168#define IDE_BUSY        0x80
 169
 170static int pcd_open(struct cdrom_device_info *cdi, int purpose);
 171static void pcd_release(struct cdrom_device_info *cdi);
 172static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
 173static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
 174static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
 175static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
 176static int pcd_drive_reset(struct cdrom_device_info *cdi);
 177static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
 178static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
 179                           unsigned int cmd, void *arg);
 180static int pcd_packet(struct cdrom_device_info *cdi,
 181                      struct packet_command *cgc);
 182
 183static int pcd_detect(void);
 184static void pcd_probe_capabilities(void);
 185static void do_pcd_read_drq(void);
 186static void do_pcd_request(struct request_queue * q);
 187static void do_pcd_read(void);
 188
 189struct pcd_unit {
 190        struct pi_adapter pia;  /* interface to paride layer */
 191        struct pi_adapter *pi;
 192        int drive;              /* master/slave */
 193        int last_sense;         /* result of last request sense */
 194        int changed;            /* media change seen */
 195        int present;            /* does this unit exist ? */
 196        char *name;             /* pcd0, pcd1, etc */
 197        struct cdrom_device_info info;  /* uniform cdrom interface */
 198        struct gendisk *disk;
 199};
 200
 201static struct pcd_unit pcd[PCD_UNITS];
 202
 203static char pcd_scratch[64];
 204static char pcd_buffer[2048];   /* raw block buffer */
 205static int pcd_bufblk = -1;     /* block in buffer, in CD units,
 206                                   -1 for nothing there. See also
 207                                   pd_unit.
 208                                 */
 209
 210/* the variables below are used mainly in the I/O request engine, which
 211   processes only one request at a time.
 212*/
 213
 214static struct pcd_unit *pcd_current; /* current request's drive */
 215static struct request *pcd_req;
 216static int pcd_retries;         /* retries on current request */
 217static int pcd_busy;            /* request being processed ? */
 218static int pcd_sector;          /* address of next requested sector */
 219static int pcd_count;           /* number of blocks still to do */
 220static char *pcd_buf;           /* buffer for request in progress */
 221
 222/* kernel glue structures */
 223
 224static int pcd_block_open(struct block_device *bdev, fmode_t mode)
 225{
 226        struct pcd_unit *cd = bdev->bd_disk->private_data;
 227        return cdrom_open(&cd->info, bdev, mode);
 228}
 229
 230static int pcd_block_release(struct gendisk *disk, fmode_t mode)
 231{
 232        struct pcd_unit *cd = disk->private_data;
 233        cdrom_release(&cd->info, mode);
 234        return 0;
 235}
 236
 237static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
 238                                unsigned cmd, unsigned long arg)
 239{
 240        struct pcd_unit *cd = bdev->bd_disk->private_data;
 241        return cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
 242}
 243
 244static int pcd_block_media_changed(struct gendisk *disk)
 245{
 246        struct pcd_unit *cd = disk->private_data;
 247        return cdrom_media_changed(&cd->info);
 248}
 249
 250static const struct block_device_operations pcd_bdops = {
 251        .owner          = THIS_MODULE,
 252        .open           = pcd_block_open,
 253        .release        = pcd_block_release,
 254        .locked_ioctl   = pcd_block_ioctl,
 255        .media_changed  = pcd_block_media_changed,
 256};
 257
 258static struct cdrom_device_ops pcd_dops = {
 259        .open           = pcd_open,
 260        .release        = pcd_release,
 261        .drive_status   = pcd_drive_status,
 262        .media_changed  = pcd_media_changed,
 263        .tray_move      = pcd_tray_move,
 264        .lock_door      = pcd_lock_door,
 265        .get_mcn        = pcd_get_mcn,
 266        .reset          = pcd_drive_reset,
 267        .audio_ioctl    = pcd_audio_ioctl,
 268        .generic_packet = pcd_packet,
 269        .capability     = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
 270                          CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
 271                          CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
 272                          CDC_CD_RW,
 273};
 274
 275static void pcd_init_units(void)
 276{
 277        struct pcd_unit *cd;
 278        int unit;
 279
 280        pcd_drive_count = 0;
 281        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 282                struct gendisk *disk = alloc_disk(1);
 283                if (!disk)
 284                        continue;
 285                cd->disk = disk;
 286                cd->pi = &cd->pia;
 287                cd->present = 0;
 288                cd->last_sense = 0;
 289                cd->changed = 1;
 290                cd->drive = (*drives[unit])[D_SLV];
 291                if ((*drives[unit])[D_PRT])
 292                        pcd_drive_count++;
 293
 294                cd->name = &cd->info.name[0];
 295                snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
 296                cd->info.ops = &pcd_dops;
 297                cd->info.handle = cd;
 298                cd->info.speed = 0;
 299                cd->info.capacity = 1;
 300                cd->info.mask = 0;
 301                disk->major = major;
 302                disk->first_minor = unit;
 303                strcpy(disk->disk_name, cd->name);      /* umm... */
 304                disk->fops = &pcd_bdops;
 305        }
 306}
 307
 308static int pcd_open(struct cdrom_device_info *cdi, int purpose)
 309{
 310        struct pcd_unit *cd = cdi->handle;
 311        if (!cd->present)
 312                return -ENODEV;
 313        return 0;
 314}
 315
 316static void pcd_release(struct cdrom_device_info *cdi)
 317{
 318}
 319
 320static inline int status_reg(struct pcd_unit *cd)
 321{
 322        return pi_read_regr(cd->pi, 1, 6);
 323}
 324
 325static inline int read_reg(struct pcd_unit *cd, int reg)
 326{
 327        return pi_read_regr(cd->pi, 0, reg);
 328}
 329
 330static inline void write_reg(struct pcd_unit *cd, int reg, int val)
 331{
 332        pi_write_regr(cd->pi, 0, reg, val);
 333}
 334
 335static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
 336{
 337        int j, r, e, s, p;
 338
 339        j = 0;
 340        while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
 341               && (j++ < PCD_SPIN))
 342                udelay(PCD_DELAY);
 343
 344        if ((r & (IDE_ERR & stop)) || (j >= PCD_SPIN)) {
 345                s = read_reg(cd, 7);
 346                e = read_reg(cd, 1);
 347                p = read_reg(cd, 2);
 348                if (j >= PCD_SPIN)
 349                        e |= 0x100;
 350                if (fun)
 351                        printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
 352                               " loop=%d phase=%d\n",
 353                               cd->name, fun, msg, r, s, e, j, p);
 354                return (s << 8) + r;
 355        }
 356        return 0;
 357}
 358
 359static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
 360{
 361        pi_connect(cd->pi);
 362
 363        write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
 364
 365        if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
 366                pi_disconnect(cd->pi);
 367                return -1;
 368        }
 369
 370        write_reg(cd, 4, dlen % 256);
 371        write_reg(cd, 5, dlen / 256);
 372        write_reg(cd, 7, 0xa0); /* ATAPI packet command */
 373
 374        if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
 375                pi_disconnect(cd->pi);
 376                return -1;
 377        }
 378
 379        if (read_reg(cd, 2) != 1) {
 380                printk("%s: %s: command phase error\n", cd->name, fun);
 381                pi_disconnect(cd->pi);
 382                return -1;
 383        }
 384
 385        pi_write_block(cd->pi, cmd, 12);
 386
 387        return 0;
 388}
 389
 390static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
 391{
 392        int r, d, p, n, k, j;
 393
 394        r = -1;
 395        k = 0;
 396        j = 0;
 397
 398        if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
 399                      fun, "completion")) {
 400                r = 0;
 401                while (read_reg(cd, 7) & IDE_DRQ) {
 402                        d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
 403                        n = (d + 3) & 0xfffc;
 404                        p = read_reg(cd, 2) & 3;
 405
 406                        if ((p == 2) && (n > 0) && (j == 0)) {
 407                                pi_read_block(cd->pi, buf, n);
 408                                if (verbose > 1)
 409                                        printk("%s: %s: Read %d bytes\n",
 410                                               cd->name, fun, n);
 411                                r = 0;
 412                                j++;
 413                        } else {
 414                                if (verbose > 1)
 415                                        printk
 416                                            ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
 417                                             cd->name, fun, p, d, k);
 418                                if (verbose < 2)
 419                                        printk_once(
 420                                            "%s: WARNING: ATAPI phase errors\n",
 421                                            cd->name);
 422                                mdelay(1);
 423                        }
 424                        if (k++ > PCD_TMO) {
 425                                printk("%s: Stuck DRQ\n", cd->name);
 426                                break;
 427                        }
 428                        if (pcd_wait
 429                            (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
 430                             "completion")) {
 431                                r = -1;
 432                                break;
 433                        }
 434                }
 435        }
 436
 437        pi_disconnect(cd->pi);
 438
 439        return r;
 440}
 441
 442static void pcd_req_sense(struct pcd_unit *cd, char *fun)
 443{
 444        char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
 445        char buf[16];
 446        int r, c;
 447
 448        r = pcd_command(cd, rs_cmd, 16, "Request sense");
 449        mdelay(1);
 450        if (!r)
 451                pcd_completion(cd, buf, "Request sense");
 452
 453        cd->last_sense = -1;
 454        c = 2;
 455        if (!r) {
 456                if (fun)
 457                        printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
 458                               cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
 459                c = buf[2] & 0xf;
 460                cd->last_sense =
 461                    c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
 462        }
 463        if ((c == 2) || (c == 6))
 464                cd->changed = 1;
 465}
 466
 467static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
 468{
 469        int r;
 470
 471        r = pcd_command(cd, cmd, dlen, fun);
 472        mdelay(1);
 473        if (!r)
 474                r = pcd_completion(cd, buf, fun);
 475        if (r)
 476                pcd_req_sense(cd, fun);
 477
 478        return r;
 479}
 480
 481static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
 482{
 483        return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
 484                         "generic packet");
 485}
 486
 487#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 488
 489static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
 490{
 491        struct pcd_unit *cd = cdi->handle;
 492        int res = cd->changed;
 493        if (res)
 494                cd->changed = 0;
 495        return res;
 496}
 497
 498static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
 499{
 500        char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
 501
 502        return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
 503                         lock ? "lock door" : "unlock door");
 504}
 505
 506static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
 507{
 508        char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
 509
 510        return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
 511                         position ? "eject" : "close tray");
 512}
 513
 514static void pcd_sleep(int cs)
 515{
 516        schedule_timeout_interruptible(cs);
 517}
 518
 519static int pcd_reset(struct pcd_unit *cd)
 520{
 521        int i, k, flg;
 522        int expect[5] = { 1, 1, 1, 0x14, 0xeb };
 523
 524        pi_connect(cd->pi);
 525        write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
 526        write_reg(cd, 7, 8);
 527
 528        pcd_sleep(20 * HZ / 1000);      /* delay a bit */
 529
 530        k = 0;
 531        while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
 532                pcd_sleep(HZ / 10);
 533
 534        flg = 1;
 535        for (i = 0; i < 5; i++)
 536                flg &= (read_reg(cd, i + 1) == expect[i]);
 537
 538        if (verbose) {
 539                printk("%s: Reset (%d) signature = ", cd->name, k);
 540                for (i = 0; i < 5; i++)
 541                        printk("%3x", read_reg(cd, i + 1));
 542                if (!flg)
 543                        printk(" (incorrect)");
 544                printk("\n");
 545        }
 546
 547        pi_disconnect(cd->pi);
 548        return flg - 1;
 549}
 550
 551static int pcd_drive_reset(struct cdrom_device_info *cdi)
 552{
 553        return pcd_reset(cdi->handle);
 554}
 555
 556static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
 557{
 558        char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 559        int k, p;
 560
 561        k = 0;
 562        while (k < tmo) {
 563                cd->last_sense = 0;
 564                pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
 565                p = cd->last_sense;
 566                if (!p)
 567                        return 0;
 568                if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
 569                        return p;
 570                k++;
 571                pcd_sleep(HZ);
 572        }
 573        return 0x000020;        /* timeout */
 574}
 575
 576static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
 577{
 578        char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 579        struct pcd_unit *cd = cdi->handle;
 580
 581        if (pcd_ready_wait(cd, PCD_READY_TMO))
 582                return CDS_DRIVE_NOT_READY;
 583        if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
 584                return CDS_NO_DISC;
 585        return CDS_DISC_OK;
 586}
 587
 588static int pcd_identify(struct pcd_unit *cd, char *id)
 589{
 590        int k, s;
 591        char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
 592
 593        pcd_bufblk = -1;
 594
 595        s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
 596
 597        if (s)
 598                return -1;
 599        if ((pcd_buffer[0] & 0x1f) != 5) {
 600                if (verbose)
 601                        printk("%s: %s is not a CD-ROM\n",
 602                               cd->name, cd->drive ? "Slave" : "Master");
 603                return -1;
 604        }
 605        memcpy(id, pcd_buffer + 16, 16);
 606        id[16] = 0;
 607        k = 16;
 608        while ((k >= 0) && (id[k] <= 0x20)) {
 609                id[k] = 0;
 610                k--;
 611        }
 612
 613        printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
 614
 615        return 0;
 616}
 617
 618/*
 619 * returns  0, with id set if drive is detected
 620 *          -1, if drive detection failed
 621 */
 622static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
 623{
 624        if (ms == -1) {
 625                for (cd->drive = 0; cd->drive <= 1; cd->drive++)
 626                        if (!pcd_reset(cd) && !pcd_identify(cd, id))
 627                                return 0;
 628        } else {
 629                cd->drive = ms;
 630                if (!pcd_reset(cd) && !pcd_identify(cd, id))
 631                        return 0;
 632        }
 633        return -1;
 634}
 635
 636static void pcd_probe_capabilities(void)
 637{
 638        int unit, r;
 639        char buffer[32];
 640        char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
 641        struct pcd_unit *cd;
 642
 643        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 644                if (!cd->present)
 645                        continue;
 646                r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
 647                if (r)
 648                        continue;
 649                /* we should now have the cap page */
 650                if ((buffer[11] & 1) == 0)
 651                        cd->info.mask |= CDC_CD_R;
 652                if ((buffer[11] & 2) == 0)
 653                        cd->info.mask |= CDC_CD_RW;
 654                if ((buffer[12] & 1) == 0)
 655                        cd->info.mask |= CDC_PLAY_AUDIO;
 656                if ((buffer[14] & 1) == 0)
 657                        cd->info.mask |= CDC_LOCK;
 658                if ((buffer[14] & 8) == 0)
 659                        cd->info.mask |= CDC_OPEN_TRAY;
 660                if ((buffer[14] >> 6) == 0)
 661                        cd->info.mask |= CDC_CLOSE_TRAY;
 662        }
 663}
 664
 665static int pcd_detect(void)
 666{
 667        char id[18];
 668        int k, unit;
 669        struct pcd_unit *cd;
 670
 671        printk("%s: %s version %s, major %d, nice %d\n",
 672               name, name, PCD_VERSION, major, nice);
 673
 674        k = 0;
 675        if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
 676                cd = pcd;
 677                if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
 678                            PI_PCD, verbose, cd->name)) {
 679                        if (!pcd_probe(cd, -1, id) && cd->disk) {
 680                                cd->present = 1;
 681                                k++;
 682                        } else
 683                                pi_release(cd->pi);
 684                }
 685        } else {
 686                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 687                        int *conf = *drives[unit];
 688                        if (!conf[D_PRT])
 689                                continue;
 690                        if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
 691                                     conf[D_UNI], conf[D_PRO], conf[D_DLY],
 692                                     pcd_buffer, PI_PCD, verbose, cd->name)) 
 693                                continue;
 694                        if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
 695                                cd->present = 1;
 696                                k++;
 697                        } else
 698                                pi_release(cd->pi);
 699                }
 700        }
 701        if (k)
 702                return 0;
 703
 704        printk("%s: No CD-ROM drive found\n", name);
 705        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 706                put_disk(cd->disk);
 707        return -1;
 708}
 709
 710/* I/O request processing */
 711static struct request_queue *pcd_queue;
 712
 713static void do_pcd_request(struct request_queue * q)
 714{
 715        if (pcd_busy)
 716                return;
 717        while (1) {
 718                if (!pcd_req) {
 719                        pcd_req = blk_fetch_request(q);
 720                        if (!pcd_req)
 721                                return;
 722                }
 723
 724                if (rq_data_dir(pcd_req) == READ) {
 725                        struct pcd_unit *cd = pcd_req->rq_disk->private_data;
 726                        if (cd != pcd_current)
 727                                pcd_bufblk = -1;
 728                        pcd_current = cd;
 729                        pcd_sector = blk_rq_pos(pcd_req);
 730                        pcd_count = blk_rq_cur_sectors(pcd_req);
 731                        pcd_buf = pcd_req->buffer;
 732                        pcd_busy = 1;
 733                        ps_set_intr(do_pcd_read, NULL, 0, nice);
 734                        return;
 735                } else {
 736                        __blk_end_request_all(pcd_req, -EIO);
 737                        pcd_req = NULL;
 738                }
 739        }
 740}
 741
 742static inline void next_request(int err)
 743{
 744        unsigned long saved_flags;
 745
 746        spin_lock_irqsave(&pcd_lock, saved_flags);
 747        if (!__blk_end_request_cur(pcd_req, err))
 748                pcd_req = NULL;
 749        pcd_busy = 0;
 750        do_pcd_request(pcd_queue);
 751        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 752}
 753
 754static int pcd_ready(void)
 755{
 756        return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
 757}
 758
 759static void pcd_transfer(void)
 760{
 761
 762        while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
 763                int o = (pcd_sector % 4) * 512;
 764                memcpy(pcd_buf, pcd_buffer + o, 512);
 765                pcd_count--;
 766                pcd_buf += 512;
 767                pcd_sector++;
 768        }
 769}
 770
 771static void pcd_start(void)
 772{
 773        int b, i;
 774        char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
 775
 776        pcd_bufblk = pcd_sector / 4;
 777        b = pcd_bufblk;
 778        for (i = 0; i < 4; i++) {
 779                rd_cmd[5 - i] = b & 0xff;
 780                b = b >> 8;
 781        }
 782
 783        if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
 784                pcd_bufblk = -1;
 785                next_request(-EIO);
 786                return;
 787        }
 788
 789        mdelay(1);
 790
 791        ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
 792}
 793
 794static void do_pcd_read(void)
 795{
 796        pcd_busy = 1;
 797        pcd_retries = 0;
 798        pcd_transfer();
 799        if (!pcd_count) {
 800                next_request(0);
 801                return;
 802        }
 803
 804        pi_do_claimed(pcd_current->pi, pcd_start);
 805}
 806
 807static void do_pcd_read_drq(void)
 808{
 809        unsigned long saved_flags;
 810
 811        if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
 812                if (pcd_retries < PCD_RETRIES) {
 813                        mdelay(1);
 814                        pcd_retries++;
 815                        pi_do_claimed(pcd_current->pi, pcd_start);
 816                        return;
 817                }
 818                pcd_bufblk = -1;
 819                next_request(-EIO);
 820                return;
 821        }
 822
 823        do_pcd_read();
 824        spin_lock_irqsave(&pcd_lock, saved_flags);
 825        do_pcd_request(pcd_queue);
 826        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 827}
 828
 829/* the audio_ioctl stuff is adapted from sr_ioctl.c */
 830
 831static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 832{
 833        struct pcd_unit *cd = cdi->handle;
 834
 835        switch (cmd) {
 836
 837        case CDROMREADTOCHDR:
 838
 839                {
 840                        char cmd[12] =
 841                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 842                         0, 0, 0 };
 843                        struct cdrom_tochdr *tochdr =
 844                            (struct cdrom_tochdr *) arg;
 845                        char buffer[32];
 846                        int r;
 847
 848                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
 849
 850                        tochdr->cdth_trk0 = buffer[2];
 851                        tochdr->cdth_trk1 = buffer[3];
 852
 853                        return r ? -EIO : 0;
 854                }
 855
 856        case CDROMREADTOCENTRY:
 857
 858                {
 859                        char cmd[12] =
 860                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 861                         0, 0, 0 };
 862
 863                        struct cdrom_tocentry *tocentry =
 864                            (struct cdrom_tocentry *) arg;
 865                        unsigned char buffer[32];
 866                        int r;
 867
 868                        cmd[1] =
 869                            (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
 870                        cmd[6] = tocentry->cdte_track;
 871
 872                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
 873
 874                        tocentry->cdte_ctrl = buffer[5] & 0xf;
 875                        tocentry->cdte_adr = buffer[5] >> 4;
 876                        tocentry->cdte_datamode =
 877                            (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
 878                        if (tocentry->cdte_format == CDROM_MSF) {
 879                                tocentry->cdte_addr.msf.minute = buffer[9];
 880                                tocentry->cdte_addr.msf.second = buffer[10];
 881                                tocentry->cdte_addr.msf.frame = buffer[11];
 882                        } else
 883                                tocentry->cdte_addr.lba =
 884                                    (((((buffer[8] << 8) + buffer[9]) << 8)
 885                                      + buffer[10]) << 8) + buffer[11];
 886
 887                        return r ? -EIO : 0;
 888                }
 889
 890        default:
 891
 892                return -ENOSYS;
 893        }
 894}
 895
 896static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 897{
 898        char cmd[12] =
 899            { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
 900        char buffer[32];
 901
 902        if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
 903                return -EIO;
 904
 905        memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 906        mcn->medium_catalog_number[13] = 0;
 907
 908        return 0;
 909}
 910
 911static int __init pcd_init(void)
 912{
 913        struct pcd_unit *cd;
 914        int unit;
 915
 916        if (disable)
 917                return -EINVAL;
 918
 919        pcd_init_units();
 920
 921        if (pcd_detect())
 922                return -ENODEV;
 923
 924        /* get the atapi capabilities page */
 925        pcd_probe_capabilities();
 926
 927        if (register_blkdev(major, name)) {
 928                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 929                        put_disk(cd->disk);
 930                return -EBUSY;
 931        }
 932
 933        pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
 934        if (!pcd_queue) {
 935                unregister_blkdev(major, name);
 936                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 937                        put_disk(cd->disk);
 938                return -ENOMEM;
 939        }
 940
 941        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 942                if (cd->present) {
 943                        register_cdrom(&cd->info);
 944                        cd->disk->private_data = cd;
 945                        cd->disk->queue = pcd_queue;
 946                        add_disk(cd->disk);
 947                }
 948        }
 949
 950        return 0;
 951}
 952
 953static void __exit pcd_exit(void)
 954{
 955        struct pcd_unit *cd;
 956        int unit;
 957
 958        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 959                if (cd->present) {
 960                        del_gendisk(cd->disk);
 961                        pi_release(cd->pi);
 962                        unregister_cdrom(&cd->info);
 963                }
 964                put_disk(cd->disk);
 965        }
 966        blk_cleanup_queue(pcd_queue);
 967        unregister_blkdev(major, name);
 968}
 969
 970MODULE_LICENSE("GPL");
 971module_init(pcd_init)
 972module_exit(pcd_exit)
 973