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