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