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, bool, 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 int 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        return 0;
 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        k = 0;
 695        if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
 696                cd = pcd;
 697                if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
 698                            PI_PCD, verbose, cd->name)) {
 699                        if (!pcd_probe(cd, -1, id) && cd->disk) {
 700                                cd->present = 1;
 701                                k++;
 702                        } else
 703                                pi_release(cd->pi);
 704                }
 705        } else {
 706                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 707                        int *conf = *drives[unit];
 708                        if (!conf[D_PRT])
 709                                continue;
 710                        if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
 711                                     conf[D_UNI], conf[D_PRO], conf[D_DLY],
 712                                     pcd_buffer, PI_PCD, verbose, cd->name)) 
 713                                continue;
 714                        if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
 715                                cd->present = 1;
 716                                k++;
 717                        } else
 718                                pi_release(cd->pi);
 719                }
 720        }
 721        if (k)
 722                return 0;
 723
 724        printk("%s: No CD-ROM drive found\n", name);
 725        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 726                put_disk(cd->disk);
 727        return -1;
 728}
 729
 730/* I/O request processing */
 731static struct request_queue *pcd_queue;
 732
 733static void do_pcd_request(struct request_queue * q)
 734{
 735        if (pcd_busy)
 736                return;
 737        while (1) {
 738                if (!pcd_req) {
 739                        pcd_req = blk_fetch_request(q);
 740                        if (!pcd_req)
 741                                return;
 742                }
 743
 744                if (rq_data_dir(pcd_req) == READ) {
 745                        struct pcd_unit *cd = pcd_req->rq_disk->private_data;
 746                        if (cd != pcd_current)
 747                                pcd_bufblk = -1;
 748                        pcd_current = cd;
 749                        pcd_sector = blk_rq_pos(pcd_req);
 750                        pcd_count = blk_rq_cur_sectors(pcd_req);
 751                        pcd_buf = pcd_req->buffer;
 752                        pcd_busy = 1;
 753                        ps_set_intr(do_pcd_read, NULL, 0, nice);
 754                        return;
 755                } else {
 756                        __blk_end_request_all(pcd_req, -EIO);
 757                        pcd_req = NULL;
 758                }
 759        }
 760}
 761
 762static inline void next_request(int err)
 763{
 764        unsigned long saved_flags;
 765
 766        spin_lock_irqsave(&pcd_lock, saved_flags);
 767        if (!__blk_end_request_cur(pcd_req, err))
 768                pcd_req = NULL;
 769        pcd_busy = 0;
 770        do_pcd_request(pcd_queue);
 771        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 772}
 773
 774static int pcd_ready(void)
 775{
 776        return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
 777}
 778
 779static void pcd_transfer(void)
 780{
 781
 782        while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
 783                int o = (pcd_sector % 4) * 512;
 784                memcpy(pcd_buf, pcd_buffer + o, 512);
 785                pcd_count--;
 786                pcd_buf += 512;
 787                pcd_sector++;
 788        }
 789}
 790
 791static void pcd_start(void)
 792{
 793        int b, i;
 794        char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
 795
 796        pcd_bufblk = pcd_sector / 4;
 797        b = pcd_bufblk;
 798        for (i = 0; i < 4; i++) {
 799                rd_cmd[5 - i] = b & 0xff;
 800                b = b >> 8;
 801        }
 802
 803        if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
 804                pcd_bufblk = -1;
 805                next_request(-EIO);
 806                return;
 807        }
 808
 809        mdelay(1);
 810
 811        ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
 812}
 813
 814static void do_pcd_read(void)
 815{
 816        pcd_busy = 1;
 817        pcd_retries = 0;
 818        pcd_transfer();
 819        if (!pcd_count) {
 820                next_request(0);
 821                return;
 822        }
 823
 824        pi_do_claimed(pcd_current->pi, pcd_start);
 825}
 826
 827static void do_pcd_read_drq(void)
 828{
 829        unsigned long saved_flags;
 830
 831        if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
 832                if (pcd_retries < PCD_RETRIES) {
 833                        mdelay(1);
 834                        pcd_retries++;
 835                        pi_do_claimed(pcd_current->pi, pcd_start);
 836                        return;
 837                }
 838                pcd_bufblk = -1;
 839                next_request(-EIO);
 840                return;
 841        }
 842
 843        do_pcd_read();
 844        spin_lock_irqsave(&pcd_lock, saved_flags);
 845        do_pcd_request(pcd_queue);
 846        spin_unlock_irqrestore(&pcd_lock, saved_flags);
 847}
 848
 849/* the audio_ioctl stuff is adapted from sr_ioctl.c */
 850
 851static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 852{
 853        struct pcd_unit *cd = cdi->handle;
 854
 855        switch (cmd) {
 856
 857        case CDROMREADTOCHDR:
 858
 859                {
 860                        char cmd[12] =
 861                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 862                         0, 0, 0 };
 863                        struct cdrom_tochdr *tochdr =
 864                            (struct cdrom_tochdr *) arg;
 865                        char buffer[32];
 866                        int r;
 867
 868                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
 869
 870                        tochdr->cdth_trk0 = buffer[2];
 871                        tochdr->cdth_trk1 = buffer[3];
 872
 873                        return r ? -EIO : 0;
 874                }
 875
 876        case CDROMREADTOCENTRY:
 877
 878                {
 879                        char cmd[12] =
 880                            { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
 881                         0, 0, 0 };
 882
 883                        struct cdrom_tocentry *tocentry =
 884                            (struct cdrom_tocentry *) arg;
 885                        unsigned char buffer[32];
 886                        int r;
 887
 888                        cmd[1] =
 889                            (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
 890                        cmd[6] = tocentry->cdte_track;
 891
 892                        r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
 893
 894                        tocentry->cdte_ctrl = buffer[5] & 0xf;
 895                        tocentry->cdte_adr = buffer[5] >> 4;
 896                        tocentry->cdte_datamode =
 897                            (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
 898                        if (tocentry->cdte_format == CDROM_MSF) {
 899                                tocentry->cdte_addr.msf.minute = buffer[9];
 900                                tocentry->cdte_addr.msf.second = buffer[10];
 901                                tocentry->cdte_addr.msf.frame = buffer[11];
 902                        } else
 903                                tocentry->cdte_addr.lba =
 904                                    (((((buffer[8] << 8) + buffer[9]) << 8)
 905                                      + buffer[10]) << 8) + buffer[11];
 906
 907                        return r ? -EIO : 0;
 908                }
 909
 910        default:
 911
 912                return -ENOSYS;
 913        }
 914}
 915
 916static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 917{
 918        char cmd[12] =
 919            { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
 920        char buffer[32];
 921
 922        if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
 923                return -EIO;
 924
 925        memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 926        mcn->medium_catalog_number[13] = 0;
 927
 928        return 0;
 929}
 930
 931static int __init pcd_init(void)
 932{
 933        struct pcd_unit *cd;
 934        int unit;
 935
 936        if (disable)
 937                return -EINVAL;
 938
 939        pcd_init_units();
 940
 941        if (pcd_detect())
 942                return -ENODEV;
 943
 944        /* get the atapi capabilities page */
 945        pcd_probe_capabilities();
 946
 947        if (register_blkdev(major, name)) {
 948                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 949                        put_disk(cd->disk);
 950                return -EBUSY;
 951        }
 952
 953        pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
 954        if (!pcd_queue) {
 955                unregister_blkdev(major, name);
 956                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 957                        put_disk(cd->disk);
 958                return -ENOMEM;
 959        }
 960
 961        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 962                if (cd->present) {
 963                        register_cdrom(&cd->info);
 964                        cd->disk->private_data = cd;
 965                        cd->disk->queue = pcd_queue;
 966                        add_disk(cd->disk);
 967                }
 968        }
 969
 970        return 0;
 971}
 972
 973static void __exit pcd_exit(void)
 974{
 975        struct pcd_unit *cd;
 976        int unit;
 977
 978        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 979                if (cd->present) {
 980                        del_gendisk(cd->disk);
 981                        pi_release(cd->pi);
 982                        unregister_cdrom(&cd->info);
 983                }
 984                put_disk(cd->disk);
 985        }
 986        blk_cleanup_queue(pcd_queue);
 987        unregister_blkdev(major, name);
 988}
 989
 990MODULE_LICENSE("GPL");
 991module_init(pcd_init)
 992module_exit(pcd_exit)
 993
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.