linux-old/drivers/cdrom/sonycd535.c
<<
>>
Prefs
   1/*
   2 * Sony CDU-535 interface device driver
   3 *
   4 * This is a modified version of the CDU-31A device driver (see below).
   5 * Changes were made using documentation for the CDU-531 (which Sony
   6 * assures me is very similar to the 535) and partial disassembly of the
   7 * DOS driver.  I used Minyard's driver and replaced the CDU-31A
   8 * commands with the CDU-531 commands.  This was complicated by a different
   9 * interface protocol with the drive.  The driver is still polled.
  10 *
  11 * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
  12 * I tried polling without the sony_sleep during the data transfers but
  13 * it did not speed things up any.
  14 *
  15 * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
  16 * with CDU-31A driver.  This is the also the number from the Linux
  17 * Device Driver Registry for the Sony Drive.  Hope nobody else is using it.
  18 *
  19 * 1993-08-29 (rgj) remove the configuring of the interface board address
  20 * from the top level configuration, you have to modify it in this file.
  21 *
  22 * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
  23 *
  24 * 1995-05-20
  25 *  Modified to support CDU-510/515 series
  26 *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
  27 *  Fixed to report verify_area() failures
  28 *      (Heiko Eissfeldt <heiko@colossus.escape.de>)
  29 *
  30 * 1995-06-01
  31 *  More changes to support CDU-510/515 series
  32 *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
  33 *
  34 * November 1999 -- Make kernel-parameter implementation work with 2.3.x 
  35 *                  Removed init_module & cleanup_module in favor of 
  36 *                  module_init & module_exit.
  37 *                  Torben Mathiasen <tmm@image.dk>
  38 *
  39 * Things to do:
  40 *  - handle errors and status better, put everything into a single word
  41 *  - use interrupts (code mostly there, but a big hole still missing)
  42 *  - handle multi-session CDs?
  43 *  - use DMA?
  44 *
  45 *  Known Bugs:
  46 *  -
  47 *
  48 *   Ken Pizzini (ken@halcyon.com)
  49 *
  50 * Original by:
  51 *   Ron Jeppesen (ronj.an@site007.saic.com)
  52 *
  53 *
  54 *------------------------------------------------------------------------
  55 * Sony CDROM interface device driver.
  56 *
  57 * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
  58 *
  59 * Colossians 3:17
  60 *
  61 * The Sony interface device driver handles Sony interface CDROM
  62 * drives and provides a complete block-level interface as well as an
  63 * ioctl() interface compatible with the Sun (as specified in
  64 * include/linux/cdrom.h).  With this interface, CDROMs can be
  65 * accessed and standard audio CDs can be played back normally.
  66 *
  67 * This interface is (unfortunately) a polled interface.  This is
  68 * because most Sony interfaces are set up with DMA and interrupts
  69 * disables.  Some (like mine) do not even have the capability to
  70 * handle interrupts or DMA.  For this reason you will see a bit of
  71 * the following:
  72 *
  73 *   snap = jiffies;
  74 *   while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
  75 *   {
  76 *              if (some_condition())
  77 *         break;
  78 *      sony_sleep();
  79 *   }
  80 *   if (some_condition not met)
  81 *   {
  82 *      return an_error;
  83 *   }
  84 *
  85 * This ugly hack waits for something to happen, sleeping a little
  86 * between every try.  (The conditional is written so that jiffies
  87 * wrap-around is handled properly.)
  88 *
  89 * One thing about these drives: They talk in MSF (Minute Second Frame) format.
  90 * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
  91 * disk.  The funny thing is that these are sent to the drive in BCD, but the
  92 * interface wants to see them in decimal.  A lot of conversion goes on.
  93 *
  94 *  Copyright (C) 1993  Corey Minyard
  95 *
  96 *  This program is free software; you can redistribute it and/or modify
  97 *  it under the terms of the GNU General Public License as published by
  98 *  the Free Software Foundation; either version 2 of the License, or
  99 *  (at your option) any later version.
 100 *
 101 *  This program is distributed in the hope that it will be useful,
 102 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 103 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 104 *  GNU General Public License for more details.
 105 *
 106 *  You should have received a copy of the GNU General Public License
 107 *  along with this program; if not, write to the Free Software
 108 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 109 *
 110 */
 111
 112
 113# include <linux/module.h>
 114
 115#include <linux/errno.h>
 116#include <linux/signal.h>
 117#include <linux/sched.h>
 118#include <linux/timer.h>
 119#include <linux/fs.h>
 120#include <linux/kernel.h>
 121#include <linux/ioport.h>
 122#include <linux/hdreg.h>
 123#include <linux/genhd.h>
 124#include <linux/mm.h>
 125#include <linux/slab.h>
 126#include <linux/init.h>
 127#include <linux/devfs_fs_kernel.h>
 128
 129#define REALLY_SLOW_IO
 130#include <asm/system.h>
 131#include <asm/io.h>
 132#include <asm/uaccess.h>
 133
 134#include <linux/cdrom.h>
 135
 136#define MAJOR_NR CDU535_CDROM_MAJOR
 137# include <linux/blk.h>
 138#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
 139#include "sonycd535.h"
 140
 141/*
 142 * this is the base address of the interface card for the Sony CDU-535
 143 * CDROM drive.  If your jumpers are set for an address other than
 144 * this one (the default), change the following line to the
 145 * proper address.
 146 */
 147#ifndef CDU535_ADDRESS
 148# define CDU535_ADDRESS                 0x340
 149#endif
 150#ifndef CDU535_INTERRUPT
 151# define CDU535_INTERRUPT               0
 152#endif
 153#ifndef CDU535_HANDLE
 154# define CDU535_HANDLE                  "cdu535"
 155#endif
 156#ifndef CDU535_MESSAGE_NAME
 157# define CDU535_MESSAGE_NAME    "Sony CDU-535"
 158#endif
 159
 160#define CDU535_BLOCK_SIZE       2048 
 161 
 162#ifndef MAX_SPINUP_RETRY
 163# define MAX_SPINUP_RETRY               3       /* 1 is sufficient for most drives... */
 164#endif
 165#ifndef RETRY_FOR_BAD_STATUS
 166# define RETRY_FOR_BAD_STATUS   100     /* in 10th of second */
 167#endif
 168
 169#ifndef DEBUG
 170# define DEBUG  1
 171#endif
 172
 173/*
 174 *  SONY535_BUFFER_SIZE determines the size of internal buffer used
 175 *  by the drive.  It must be at least 2K and the larger the buffer
 176 *  the better the transfer rate.  It does however take system memory.
 177 *  On my system I get the following transfer rates using dd to read
 178 *  10 Mb off /dev/cdrom.
 179 *
 180 *    8K buffer      43 Kb/sec
 181 *   16K buffer      66 Kb/sec
 182 *   32K buffer      91 Kb/sec
 183 *   64K buffer     111 Kb/sec
 184 *  128K buffer     123 Kb/sec
 185 *  512K buffer     123 Kb/sec
 186 */
 187#define SONY535_BUFFER_SIZE     (64*1024)
 188
 189/*
 190 *  if LOCK_DOORS is defined then the eject button is disabled while
 191 * the device is open.
 192 */
 193#ifndef NO_LOCK_DOORS
 194# define LOCK_DOORS
 195#endif
 196
 197static int read_subcode(void);
 198static void sony_get_toc(void);
 199static int cdu_open(struct inode *inode, struct file *filp);
 200static inline unsigned int int_to_bcd(unsigned int val);
 201static unsigned int bcd_to_int(unsigned int bcd);
 202static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
 203                                           Byte * response, int n_response, int ignoreStatusBit7);
 204
 205/* The base I/O address of the Sony Interface.  This is a variable (not a
 206   #define) so it can be easily changed via some future ioctl() */
 207static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
 208MODULE_PARM(sony535_cd_base_io, "i");
 209
 210/*
 211 * The following are I/O addresses of the various registers for the drive.  The
 212 * comment for the base address also applies here.
 213 */
 214static unsigned short select_unit_reg;
 215static unsigned short result_reg;
 216static unsigned short command_reg;
 217static unsigned short read_status_reg;
 218static unsigned short data_reg;
 219
 220static int initialized;                 /* Has the drive been initialized? */
 221static int sony_disc_changed = 1;       /* Has the disk been changed
 222                                           since the last check? */
 223static int sony_toc_read;               /* Has the table of contents been
 224                                           read? */
 225static unsigned int sony_buffer_size;   /* Size in bytes of the read-ahead
 226                                           buffer. */
 227static unsigned int sony_buffer_sectors;        /* Size (in 2048 byte records) of
 228                                                   the read-ahead buffer. */
 229static unsigned int sony_usage;         /* How many processes have the
 230                                           drive open. */
 231
 232static int sony_first_block = -1;       /* First OS block (512 byte) in
 233                                           the read-ahead buffer */
 234static int sony_last_block = -1;        /* Last OS block (512 byte) in
 235                                           the read-ahead buffer */
 236
 237static struct s535_sony_toc *sony_toc;  /* Points to the table of
 238                                           contents. */
 239
 240static struct s535_sony_subcode *last_sony_subcode;             /* Points to the last
 241                                                                   subcode address read */
 242static Byte **sony_buffer;              /* Points to the pointers
 243                                           to the sector buffers */
 244
 245static int sony_inuse;                  /* is the drive in use? Only one
 246                                           open at a time allowed */
 247
 248/*
 249 * The audio status uses the values from read subchannel data as specified
 250 * in include/linux/cdrom.h.
 251 */
 252static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
 253
 254/*
 255 * The following are a hack for pausing and resuming audio play.  The drive
 256 * does not work as I would expect it, if you stop it then start it again,
 257 * the drive seeks back to the beginning and starts over.  This holds the
 258 * position during a pause so a resume can restart it.  It uses the
 259 * audio status variable above to tell if it is paused.
 260 *   I just kept the CDU-31A driver behavior rather than using the PAUSE
 261 * command on the CDU-535.
 262 */
 263static Byte cur_pos_msf[3];
 264static Byte final_pos_msf[3];
 265
 266/* What IRQ is the drive using?  0 if none. */
 267static int sony535_irq_used = CDU535_INTERRUPT;
 268
 269/* The interrupt handler will wake this queue up when it gets an interrupt. */
 270static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
 271
 272
 273/*
 274 * This routine returns 1 if the disk has been changed since the last
 275 * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
 276 */
 277static int
 278cdu535_check_media_change(kdev_t full_dev)
 279{
 280        int retval;
 281
 282        if (MINOR(full_dev) != 0) {
 283                printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
 284                return 0;
 285        }
 286
 287        /* if driver is not initialized, always return 0 */
 288        retval = initialized ? sony_disc_changed : 0;
 289        sony_disc_changed = 0;
 290        return retval;
 291}
 292
 293static inline void
 294enable_interrupts(void)
 295{
 296#ifdef USE_IRQ
 297        /*
 298         * This code was taken from cdu31a.c; it will not
 299         * directly work for the cdu535 as written...
 300         */
 301        curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
 302                                                | SONY_RES_RDY_INT_EN_BIT
 303                                                | SONY_DATA_RDY_INT_EN_BIT);
 304        outb(curr_control_reg, sony_cd_control_reg);
 305#endif
 306}
 307
 308static inline void
 309disable_interrupts(void)
 310{
 311#ifdef USE_IRQ
 312        /*
 313         * This code was taken from cdu31a.c; it will not
 314         * directly work for the cdu535 as written...
 315         */
 316        curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
 317                                                | SONY_RES_RDY_INT_EN_BIT
 318                                                | SONY_DATA_RDY_INT_EN_BIT);
 319        outb(curr_control_reg, sony_cd_control_reg);
 320#endif
 321}
 322
 323static void
 324cdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 325{
 326        disable_interrupts();
 327        if (waitqueue_active(&cdu535_irq_wait))
 328                wake_up(&cdu535_irq_wait);
 329        else
 330                printk(CDU535_MESSAGE_NAME
 331                                ": Got an interrupt but nothing was waiting\n");
 332}
 333
 334
 335/*
 336 * Wait a little while.
 337 */
 338static inline void
 339sony_sleep(void)
 340{
 341        if (sony535_irq_used <= 0) {    /* poll */
 342                current->state = TASK_INTERRUPTIBLE;
 343                schedule_timeout(0);
 344        } else {        /* Interrupt driven */
 345                cli();
 346                enable_interrupts();
 347                interruptible_sleep_on(&cdu535_irq_wait);
 348                sti();
 349        }
 350}
 351
 352/*------------------start of SONY CDU535 very specific ---------------------*/
 353
 354/****************************************************************************
 355 * void select_unit( int unit_no )
 356 *
 357 *  Select the specified unit (0-3) so that subsequent commands reference it
 358 ****************************************************************************/
 359static void
 360select_unit(int unit_no)
 361{
 362        unsigned int select_mask = ~(1 << unit_no);
 363        outb(select_mask, select_unit_reg);
 364}
 365
 366/***************************************************************************
 367 * int read_result_reg( Byte *data_ptr )
 368 *
 369 *  Read a result byte from the Sony CDU controller, store in location pointed
 370 * to by data_ptr.  Return zero on success, TIME_OUT if we did not receive
 371 * data.
 372 ***************************************************************************/
 373static int
 374read_result_reg(Byte *data_ptr)
 375{
 376        unsigned long snap;
 377        int read_status;
 378
 379        snap = jiffies;
 380        while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
 381                read_status = inb(read_status_reg);
 382                if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
 383#if DEBUG > 1
 384                        printk(CDU535_MESSAGE_NAME
 385                                        ": read_result_reg(): readStatReg = 0x%x\n", read_status);
 386#endif
 387                        *data_ptr = inb(result_reg);
 388                        return 0;
 389                } else {
 390                        sony_sleep();
 391                }
 392        }
 393        printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
 394        return TIME_OUT;
 395}
 396
 397/****************************************************************************
 398 * int read_exec_status( Byte status[2] )
 399 *
 400 *  Read the execution status of the last command and put into status.
 401 * Handles reading second status word if available.  Returns 0 on success,
 402 * TIME_OUT on failure.
 403 ****************************************************************************/
 404static int
 405read_exec_status(Byte status[2])
 406{
 407        status[1] = 0;
 408        if (read_result_reg(&(status[0])) != 0)
 409                return TIME_OUT;
 410        if ((status[0] & 0x80) != 0) {  /* byte two follows */
 411                if (read_result_reg(&(status[1])) != 0)
 412                        return TIME_OUT;
 413        }
 414#if DEBUG > 1
 415        printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
 416                        status[0], status[1]);
 417#endif
 418        return 0;
 419}
 420
 421/****************************************************************************
 422 * int check_drive_status( void )
 423 *
 424 *  Check the current drive status.  Using this before executing a command
 425 * takes care of the problem of unsolicited drive status-2 messages.
 426 * Add a check of the audio status if we think the disk is playing.
 427 ****************************************************************************/
 428static int
 429check_drive_status(void)
 430{
 431        Byte status, e_status[2];
 432        int  CDD, ATN;
 433        Byte cmd;
 434
 435        select_unit(0);
 436        if (sony_audio_status == CDROM_AUDIO_PLAY) {    /* check status */
 437                outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
 438                if (read_result_reg(&status) == 0) {
 439                        switch (status) {
 440                        case 0x0:
 441                                break;          /* play in progress */
 442                        case 0x1:
 443                                break;          /* paused */
 444                        case 0x3:               /* audio play completed */
 445                        case 0x5:               /* play not requested */
 446                                sony_audio_status = CDROM_AUDIO_COMPLETED;
 447                                read_subcode();
 448                                break;
 449                        case 0x4:               /* error during play */
 450                                sony_audio_status = CDROM_AUDIO_ERROR;
 451                                break;
 452                        }
 453                }
 454        }
 455        /* now check drive status */
 456        outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
 457        if (read_result_reg(&status) != 0)
 458                return TIME_OUT;
 459
 460#if DEBUG > 1
 461        printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
 462#endif
 463
 464        if (status == 0)
 465                return 0;
 466
 467        ATN = status & 0xf;
 468        CDD = (status >> 4) & 0xf;
 469
 470        switch (ATN) {
 471        case 0x0:
 472                break;                                  /* go on to CDD stuff */
 473        case SONY535_ATN_BUSY:
 474                if (initialized)
 475                        printk(CDU535_MESSAGE_NAME " error: drive busy\n");
 476                return CD_BUSY;
 477        case SONY535_ATN_EJECT_IN_PROGRESS:
 478                printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
 479                sony_audio_status = CDROM_AUDIO_INVALID;
 480                return CD_BUSY;
 481        case SONY535_ATN_RESET_OCCURRED:
 482        case SONY535_ATN_DISC_CHANGED:
 483        case SONY535_ATN_RESET_AND_DISC_CHANGED:
 484#if DEBUG > 0
 485                printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
 486#endif
 487                sony_disc_changed = 1;
 488                sony_toc_read = 0;
 489                sony_audio_status = CDROM_AUDIO_NO_STATUS;
 490                sony_first_block = -1;
 491                sony_last_block = -1;
 492                if (initialized) {
 493                        cmd = SONY535_SPIN_UP;
 494                        do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
 495                        sony_get_toc();
 496                }
 497                return 0;
 498        default:
 499                printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
 500                return CD_BUSY;
 501        }
 502        switch (CDD) {                  /* the 531 docs are not helpful in decoding this */
 503        case 0x0:                               /* just use the values from the DOS driver */
 504        case 0x2:
 505        case 0xa:
 506                break;                          /* no error */
 507        case 0xc:
 508                printk(CDU535_MESSAGE_NAME
 509                                ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
 510                return CD_BUSY;         /* ? */
 511        default:
 512                return CD_BUSY;
 513        }
 514        return 0;
 515}       /* check_drive_status() */
 516
 517/*****************************************************************************
 518 * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
 519 *                Byte *response, int n_response, int ignore_status_bit7 )
 520 *
 521 *  Generic routine for executing commands.  The command and its parameters
 522 *  should be placed in the cmd[] array, number of bytes in the command is
 523 *  stored in nCmd.  The response from the command will be stored in the
 524 *  response array.  The number of bytes you expect back (excluding status)
 525 *  should be passed in n_response.  Finally, some
 526 *  commands set bit 7 of the return status even when there is no second
 527 *  status byte, on these commands set ignoreStatusBit7 TRUE.
 528 *    If the command was sent and data received back, then we return 0,
 529 *  else we return TIME_OUT.  You still have to check the status yourself.
 530 *    You should call check_drive_status() before calling this routine
 531 *  so that you do not lose notifications of disk changes, etc.
 532 ****************************************************************************/
 533static int
 534do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
 535                        Byte * response, int n_response, int ignore_status_bit7)
 536{
 537        int i;
 538
 539        /* write out the command */
 540        for (i = 0; i < n_cmd; i++)
 541                outb(cmd[i], command_reg);
 542
 543        /* read back the status */
 544        if (read_result_reg(status) != 0)
 545                return TIME_OUT;
 546        if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
 547                /* get second status byte */
 548                if (read_result_reg(status + 1) != 0)
 549                        return TIME_OUT;
 550        } else {
 551                status[1] = 0;
 552        }
 553#if DEBUG > 2
 554        printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
 555                        *cmd, status[0], status[1]);
 556#endif
 557
 558        /* do not know about when I should read set of data and when not to */
 559        if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
 560                return 0;
 561
 562        /* else, read in rest of data */
 563        for (i = 0; 0 < n_response; n_response--, i++)
 564                if (read_result_reg(response + i) != 0)
 565                        return TIME_OUT;
 566        return 0;
 567}       /* do_sony_cmd() */
 568
 569/**************************************************************************
 570 * int set_drive_mode( int mode, Byte status[2] )
 571 *
 572 *  Set the drive mode to the specified value (mode=0 is audio, mode=e0
 573 * is mode-1 CDROM
 574 **************************************************************************/
 575static int
 576set_drive_mode(int mode, Byte status[2])
 577{
 578        Byte cmd_buff[2];
 579        Byte ret_buff[1];
 580
 581        cmd_buff[0] = SONY535_SET_DRIVE_MODE;
 582        cmd_buff[1] = mode;
 583        return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
 584}
 585
 586/***************************************************************************
 587 * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
 588 *                             Byte *data_buff, int buff_size )
 589 *
 590 *  Read n_blocks of data from the CDROM starting at position params[0:2],
 591 *  number of blocks in stored in params[3:5] -- both these are already
 592 *  int bcd format.
 593 *  Transfer the data into the buffer pointed at by data_buff.  buff_size
 594 *  gives the number of bytes available in the buffer.
 595 *    The routine returns number of bytes read in if successful, otherwise
 596 *  it returns one of the standard error returns.
 597 ***************************************************************************/
 598static int
 599seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
 600                                           Byte **buff, int buf_size)
 601{
 602        Byte cmd_buff[7];
 603        int  i;
 604        int  read_status;
 605        unsigned long snap;
 606        Byte *data_buff;
 607        int  sector_count = 0;
 608
 609        if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
 610                return NO_ROOM;
 611
 612        set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
 613
 614        /* send command to read the data */
 615        cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
 616        for (i = 0; i < 6; i++)
 617                cmd_buff[i + 1] = params[i];
 618        for (i = 0; i < 7; i++)
 619                outb(cmd_buff[i], command_reg);
 620
 621        /* read back the data one block at a time */
 622        while (0 < n_blocks--) {
 623                /* wait for data to be ready */
 624                int data_valid = 0;
 625                snap = jiffies;
 626                while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
 627                        read_status = inb(read_status_reg);
 628                        if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
 629                                read_exec_status(status);
 630                                return BAD_STATUS;
 631                        }
 632                        if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
 633                                /* data is ready, read it */
 634                                data_buff = buff[sector_count++];
 635                                for (i = 0; i < CDU535_BLOCK_SIZE; i++)
 636                                        *data_buff++ = inb(data_reg);   /* unrolling this loop does not seem to help */
 637                                data_valid = 1;
 638                                break;                  /* exit the timeout loop */
 639                        }
 640                        sony_sleep();           /* data not ready, sleep a while */
 641                }
 642                if (!data_valid)
 643                        return TIME_OUT;        /* if we reach this stage */
 644        }
 645
 646        /* read all the data, now read the status */
 647        if ((i = read_exec_status(status)) != 0)
 648                return i;
 649        return CDU535_BLOCK_SIZE * sector_count;
 650}       /* seek_and_read_N_blocks() */
 651
 652/****************************************************************************
 653 * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
 654 *
 655 *  Read in the table of contents data.  Converts all the bcd data
 656 * into integers in the toc structure.
 657 ****************************************************************************/
 658static int
 659request_toc_data(Byte status[2], struct s535_sony_toc *toc)
 660{
 661        int  to_status;
 662        int  i, j, n_tracks, track_no;
 663        int  first_track_num, last_track_num;
 664        Byte cmd_no = 0xb2;
 665        Byte track_address_buffer[5];
 666
 667        /* read the fixed portion of the table of contents */
 668        if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
 669                return to_status;
 670
 671        /* convert the data into integers so we can use them */
 672        first_track_num = bcd_to_int(toc->first_track_num);
 673        last_track_num = bcd_to_int(toc->last_track_num);
 674        n_tracks = last_track_num - first_track_num + 1;
 675
 676        /* read each of the track address descriptors */
 677        for (i = 0; i < n_tracks; i++) {
 678                /* read the descriptor into a temporary buffer */
 679                for (j = 0; j < 5; j++) {
 680                        if (read_result_reg(track_address_buffer + j) != 0)
 681                                return TIME_OUT;
 682                        if (j == 1)             /* need to convert from bcd */
 683                                track_no = bcd_to_int(track_address_buffer[j]);
 684                }
 685                /* copy the descriptor to proper location - sonycd.c just fills */
 686                memcpy(toc->tracks + i, track_address_buffer, 5);
 687        }
 688        return 0;
 689}       /* request_toc_data() */
 690
 691/***************************************************************************
 692 * int spin_up_drive( Byte status[2] )
 693 *
 694 *  Spin up the drive (unless it is already spinning).
 695 ***************************************************************************/
 696static int
 697spin_up_drive(Byte status[2])
 698{
 699        Byte cmd;
 700
 701        /* first see if the drive is already spinning */
 702        cmd = SONY535_REQUEST_DRIVE_STATUS_1;
 703        if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
 704                return TIME_OUT;
 705        if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
 706                return 0;       /* it's already spinning */
 707
 708        /* otherwise, give the spin-up command */
 709        cmd = SONY535_SPIN_UP;
 710        return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
 711}
 712
 713/*--------------------end of SONY CDU535 very specific ---------------------*/
 714
 715/* Convert from an integer 0-99 to BCD */
 716static inline unsigned int
 717int_to_bcd(unsigned int val)
 718{
 719        int retval;
 720
 721        retval = (val / 10) << 4;
 722        retval = retval | val % 10;
 723        return retval;
 724}
 725
 726
 727/* Convert from BCD to an integer from 0-99 */
 728static unsigned int
 729bcd_to_int(unsigned int bcd)
 730{
 731        return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
 732}
 733
 734
 735/*
 736 * Convert a logical sector value (like the OS would want to use for
 737 * a block device) to an MSF format.
 738 */
 739static void
 740log_to_msf(unsigned int log, Byte *msf)
 741{
 742        log = log + LOG_START_OFFSET;
 743        msf[0] = int_to_bcd(log / 4500);
 744        log = log % 4500;
 745        msf[1] = int_to_bcd(log / 75);
 746        msf[2] = int_to_bcd(log % 75);
 747}
 748
 749
 750/*
 751 * Convert an MSF format to a logical sector.
 752 */
 753static unsigned int
 754msf_to_log(Byte *msf)
 755{
 756        unsigned int log;
 757
 758
 759        log = bcd_to_int(msf[2]);
 760        log += bcd_to_int(msf[1]) * 75;
 761        log += bcd_to_int(msf[0]) * 4500;
 762        log = log - LOG_START_OFFSET;
 763
 764        return log;
 765}
 766
 767
 768/*
 769 * Take in integer size value and put it into a buffer like
 770 * the drive would want to see a number-of-sector value.
 771 */
 772static void
 773size_to_buf(unsigned int size, Byte *buf)
 774{
 775        buf[0] = size / 65536;
 776        size = size % 65536;
 777        buf[1] = size / 256;
 778        buf[2] = size % 256;
 779}
 780
 781
 782/*
 783 * The OS calls this to perform a read or write operation to the drive.
 784 * Write obviously fail.  Reads to a read ahead of sony_buffer_size
 785 * bytes to help speed operations.  This especially helps since the OS
 786 * may use 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
 787 * data access on a CD is done sequentially, this saves a lot of operations.
 788 */
 789static void
 790do_cdu535_request(request_queue_t * q)
 791{
 792        unsigned int dev;
 793        unsigned int read_size;
 794        int  block;
 795        int  nsect;
 796        int  copyoff;
 797        int  spin_up_retry;
 798        Byte params[10];
 799        Byte status[2];
 800        Byte cmd[2];
 801
 802        while (1) {
 803                /*
 804                 * The beginning here is stolen from the hard disk driver.  I hope
 805                 * it's right.
 806                 */
 807                if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) {
 808                        return;
 809                }
 810                INIT_REQUEST;
 811                dev = MINOR(CURRENT->rq_dev);
 812                block = CURRENT->sector;
 813                nsect = CURRENT->nr_sectors;
 814                if (dev != 0) {
 815                        end_request(0);
 816                        continue;
 817                }
 818                switch (CURRENT->cmd) {
 819                case READ:
 820                        /*
 821                         * If the block address is invalid or the request goes beyond the end of
 822                         * the media, return an error.
 823                         */
 824
 825                        if (sony_toc->lead_out_start_lba <= (block / 4)) {
 826                                end_request(0);
 827                                return;
 828                        }
 829                        if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
 830                                end_request(0);
 831                                return;
 832                        }
 833                        while (0 < nsect) {
 834                                /*
 835                                 * If the requested sector is not currently in the read-ahead buffer,
 836                                 * it must be read in.
 837                                 */
 838                                if ((block < sony_first_block) || (sony_last_block < block)) {
 839                                        sony_first_block = (block / 4) * 4;
 840                                        log_to_msf(block / 4, params);
 841
 842                                        /*
 843                                         * If the full read-ahead would go beyond the end of the media, trim
 844                                         * it back to read just till the end of the media.
 845                                         */
 846                                        if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
 847                                                sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
 848                                                read_size = sony_toc->lead_out_start_lba - (block / 4);
 849                                        } else {
 850                                                sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
 851                                                read_size = sony_buffer_sectors;
 852                                        }
 853                                        size_to_buf(read_size, &params[3]);
 854
 855                                        /*
 856                                         * Read the data.  If the drive was not spinning,
 857                                         * spin it up and try some more.
 858                                         */
 859                                        for (spin_up_retry=0 ;; ++spin_up_retry) {
 860                                                /* This loop has been modified to support the Sony
 861                                                 * CDU-510/515 series, thanks to Claudio Porfiri 
 862                                                 * <C.Porfiri@nisms.tei.ericsson.se>.
 863                                                 */
 864                                                /*
 865                                                 * This part is to deal with very slow hardware.  We
 866                                                 * try at most MAX_SPINUP_RETRY times to read the same
 867                                                 * block.  A check for seek_and_read_N_blocks' result is
 868                                                 * performed; if the result is wrong, the CDROM's engine
 869                                                 * is restarted and the operation is tried again.
 870                                                 */
 871                                                /*
 872                                                 * 1995-06-01: The system got problems when downloading
 873                                                 * from Slackware CDROM, the problem seems to be:
 874                                                 * seek_and_read_N_blocks returns BAD_STATUS and we
 875                                                 * should wait for a while before retrying, so a new
 876                                                 * part was added to discriminate the return value from
 877                                                 * seek_and_read_N_blocks for the various cases.
 878                                                 */
 879                                                int readStatus = seek_and_read_N_blocks(params, read_size,
 880                                                                        status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
 881                                                if (0 <= readStatus)    /* Good data; common case, placed first */
 882                                                        break;
 883                                                if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
 884                                                        /* give up */
 885                                                        if (readStatus == NO_ROOM)
 886                                                                printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
 887                                                        else
 888                                                                printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
 889                                                                                status[0]);
 890                                                        sony_first_block = -1;
 891                                                        sony_last_block = -1;
 892                                                        end_request(0);
 893                                                        return;
 894                                                }
 895                                                if (readStatus == BAD_STATUS) {
 896                                                        /* Sleep for a while, then retry */
 897                                                        current->state = TASK_INTERRUPTIBLE;
 898                                                        schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
 899                                                }
 900#if DEBUG > 0
 901                                                printk(CDU535_MESSAGE_NAME
 902                                                        " debug: calling spin up when reading data!\n");
 903#endif
 904                                                cmd[0] = SONY535_SPIN_UP;
 905                                                do_sony_cmd(cmd, 1, status, NULL, 0, 0);
 906                                        }
 907                                }
 908                                /*
 909                                 * The data is in memory now, copy it to the buffer and advance to the
 910                                 * next block to read.
 911                                 */
 912                                copyoff = block - sony_first_block;
 913                                memcpy(CURRENT->buffer,
 914                                           sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
 915
 916                                block += 1;
 917                                nsect -= 1;
 918                                CURRENT->buffer += 512;
 919                        }
 920
 921                        end_request(1);
 922                        break;
 923
 924                case WRITE:
 925                        end_request(0);
 926                        break;
 927
 928                default:
 929                        panic("Unknown SONY CD cmd");
 930                }
 931        }
 932}
 933
 934
 935/*
 936 * Read the table of contents from the drive and set sony_toc_read if
 937 * successful.
 938 */
 939static void
 940sony_get_toc(void)
 941{
 942        Byte status[2];
 943        if (!sony_toc_read) {
 944                /* do not call check_drive_status() from here since it can call this routine */
 945                if (request_toc_data(status, sony_toc) < 0)
 946                        return;
 947                sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
 948                sony_toc_read = 1;
 949        }
 950}
 951
 952
 953/*
 954 * Search for a specific track in the table of contents.  track is
 955 * passed in bcd format
 956 */
 957static int
 958find_track(int track)
 959{
 960        int i;
 961        int num_tracks;
 962
 963
 964        num_tracks = bcd_to_int(sony_toc->last_track_num) -
 965                bcd_to_int(sony_toc->first_track_num) + 1;
 966        for (i = 0; i < num_tracks; i++) {
 967                if (sony_toc->tracks[i].track == track) {
 968                        return i;
 969                }
 970        }
 971
 972        return -1;
 973}
 974
 975/*
 976 * Read the subcode and put it int last_sony_subcode for future use.
 977 */
 978static int
 979read_subcode(void)
 980{
 981        Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
 982        Byte status[2];
 983        int  dsc_status;
 984
 985        if (check_drive_status() != 0)
 986                return -EIO;
 987
 988        if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
 989                                                           sizeof(struct s535_sony_subcode), 1)) != 0) {
 990                printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
 991                                status[0], dsc_status);
 992                return -EIO;
 993        }
 994        return 0;
 995}
 996
 997
 998/*
 999 * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
1000 * the drive is playing, the subchannel needs to be read (since it would be
1001 * changing).  If the drive is paused or completed, the subcode information has
1002 * already been stored, just use that.  The ioctl call wants things in decimal
1003 * (not BCD), so all the conversions are done.
1004 */
1005static int
1006sony_get_subchnl_info(long arg)
1007{
1008        struct cdrom_subchnl schi;
1009        int err;
1010
1011        /* Get attention stuff */
1012        if (check_drive_status() != 0)
1013                return -EIO;
1014
1015        sony_get_toc();
1016        if (!sony_toc_read) {
1017                return -EIO;
1018        }
1019        err = verify_area(VERIFY_WRITE /* and read */ , (char *)arg, sizeof schi);
1020        if (err)
1021                return err;
1022
1023        copy_from_user(&schi, (char *)arg, sizeof schi);
1024
1025        switch (sony_audio_status) {
1026        case CDROM_AUDIO_PLAY:
1027                if (read_subcode() < 0) {
1028                        return -EIO;
1029                }
1030                break;
1031
1032        case CDROM_AUDIO_PAUSED:
1033        case CDROM_AUDIO_COMPLETED:
1034                break;
1035
1036        case CDROM_AUDIO_NO_STATUS:
1037                schi.cdsc_audiostatus = sony_audio_status;
1038                copy_to_user((char *)arg, &schi, sizeof schi);
1039                return 0;
1040                break;
1041
1042        case CDROM_AUDIO_INVALID:
1043        case CDROM_AUDIO_ERROR:
1044        default:
1045                return -EIO;
1046        }
1047
1048        schi.cdsc_audiostatus = sony_audio_status;
1049        schi.cdsc_adr = last_sony_subcode->address;
1050        schi.cdsc_ctrl = last_sony_subcode->control;
1051        schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
1052        schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
1053        if (schi.cdsc_format == CDROM_MSF) {
1054                schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
1055                schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
1056                schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
1057
1058                schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
1059                schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
1060                schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
1061        } else if (schi.cdsc_format == CDROM_LBA) {
1062                schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
1063                schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
1064        }
1065        copy_to_user((char *)arg, &schi, sizeof schi);
1066        return 0;
1067}
1068
1069
1070/*
1071 * The big ugly ioctl handler.
1072 */
1073static int
1074cdu_ioctl(struct inode *inode,
1075                  struct file *file,
1076                  unsigned int cmd,
1077                  unsigned long arg)
1078{
1079        unsigned int dev;
1080        Byte status[2];
1081        Byte cmd_buff[10], params[10];
1082        int  i;
1083        int  dsc_status;
1084        int  err;
1085
1086        if (!inode) {
1087                return -EINVAL;
1088        }
1089        dev = MINOR(inode->i_rdev) >> 6;
1090        if (dev != 0) {
1091                return -EINVAL;
1092        }
1093        if (check_drive_status() != 0)
1094                return -EIO;
1095
1096        switch (cmd) {
1097        case CDROMSTART:                        /* Spin up the drive */
1098                if (spin_up_drive(status) < 0) {
1099                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
1100                                        status[0]);
1101                        return -EIO;
1102                }
1103                return 0;
1104                break;
1105
1106        case CDROMSTOP:                 /* Spin down the drive */
1107                cmd_buff[0] = SONY535_HOLD;
1108                do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1109
1110                /*
1111                 * Spin the drive down, ignoring the error if the disk was
1112                 * already not spinning.
1113                 */
1114                sony_audio_status = CDROM_AUDIO_NO_STATUS;
1115                cmd_buff[0] = SONY535_SPIN_DOWN;
1116                dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1117                if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
1118                        ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
1119                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
1120                                        status[0]);
1121                        return -EIO;
1122                }
1123                return 0;
1124                break;
1125
1126        case CDROMPAUSE:                        /* Pause the drive */
1127                cmd_buff[0] = SONY535_HOLD;             /* CDU-31 driver uses AUDIO_STOP, not pause */
1128                if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1129                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
1130                                        status[0]);
1131                        return -EIO;
1132                }
1133                /* Get the current position and save it for resuming */
1134                if (read_subcode() < 0) {
1135                        return -EIO;
1136                }
1137                cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
1138                cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
1139                cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
1140                sony_audio_status = CDROM_AUDIO_PAUSED;
1141                return 0;
1142                break;
1143
1144        case CDROMRESUME:                       /* Start the drive after being paused */
1145                set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1146
1147                if (sony_audio_status != CDROM_AUDIO_PAUSED) {
1148                        return -EINVAL;
1149                }
1150                spin_up_drive(status);
1151
1152                /* Start the drive at the saved position. */
1153                cmd_buff[0] = SONY535_PLAY_AUDIO;
1154                cmd_buff[1] = 0;                /* play back starting at this address */
1155                cmd_buff[2] = cur_pos_msf[0];
1156                cmd_buff[3] = cur_pos_msf[1];
1157                cmd_buff[4] = cur_pos_msf[2];
1158                cmd_buff[5] = SONY535_PLAY_AUDIO;
1159                cmd_buff[6] = 2;                /* set ending address */
1160                cmd_buff[7] = final_pos_msf[0];
1161                cmd_buff[8] = final_pos_msf[1];
1162                cmd_buff[9] = final_pos_msf[2];
1163                if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1164                        (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1165                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
1166                                        status[0]);
1167                        return -EIO;
1168                }
1169                sony_audio_status = CDROM_AUDIO_PLAY;
1170                return 0;
1171                break;
1172
1173        case CDROMPLAYMSF:                      /* Play starting at the given MSF address. */
1174                err = verify_area(VERIFY_READ, (char *)arg, 6);
1175                if (err)
1176                        return err;
1177                spin_up_drive(status);
1178                set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1179                copy_from_user(params, (void *)arg, 6);
1180
1181                /* The parameters are given in int, must be converted */
1182                for (i = 0; i < 3; i++) {
1183                        cmd_buff[2 + i] = int_to_bcd(params[i]);
1184                        cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
1185                }
1186                cmd_buff[0] = SONY535_PLAY_AUDIO;
1187                cmd_buff[1] = 0;                /* play back starting at this address */
1188                /* cmd_buff[2-4] are filled in for loop above */
1189                cmd_buff[5] = SONY535_PLAY_AUDIO;
1190                cmd_buff[6] = 2;                /* set ending address */
1191                /* cmd_buff[7-9] are filled in for loop above */
1192                if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1193                        (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1194                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
1195                                        status[0]);
1196                        return -EIO;
1197                }
1198                /* Save the final position for pauses and resumes */
1199                final_pos_msf[0] = cmd_buff[7];
1200                final_pos_msf[1] = cmd_buff[8];
1201                final_pos_msf[2] = cmd_buff[9];
1202                sony_audio_status = CDROM_AUDIO_PLAY;
1203                return 0;
1204                break;
1205
1206        case CDROMREADTOCHDR:           /* Read the table of contents header */
1207                {
1208                        struct cdrom_tochdr *hdr;
1209                        struct cdrom_tochdr loc_hdr;
1210
1211                        sony_get_toc();
1212                        if (!sony_toc_read)
1213                                return -EIO;
1214                        hdr = (struct cdrom_tochdr *)arg;
1215                        err = verify_area(VERIFY_WRITE, hdr, sizeof *hdr);
1216                        if (err)
1217                                return err;
1218                        loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
1219                        loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
1220                        copy_to_user(hdr, &loc_hdr, sizeof *hdr);
1221                }
1222                return 0;
1223                break;
1224
1225        case CDROMREADTOCENTRY: /* Read a given table of contents entry */
1226                {
1227                        struct cdrom_tocentry *entry;
1228                        struct cdrom_tocentry loc_entry;
1229                        int  track_idx;
1230                        Byte *msf_val = NULL;
1231
1232                        sony_get_toc();
1233                        if (!sony_toc_read) {
1234                                return -EIO;
1235                        }
1236                        entry = (struct cdrom_tocentry *)arg;
1237                        err = verify_area(VERIFY_WRITE /* and read */ , entry, sizeof *entry);
1238                        if (err)
1239                                return err;
1240
1241                        copy_from_user(&loc_entry, entry, sizeof loc_entry);
1242
1243                        /* Lead out is handled separately since it is special. */
1244                        if (loc_entry.cdte_track == CDROM_LEADOUT) {
1245                                loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
1246                                loc_entry.cdte_ctrl = sony_toc->control2;
1247                                msf_val = sony_toc->lead_out_start_msf;
1248                        } else {
1249                                track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
1250                                if (track_idx < 0)
1251                                        return -EINVAL;
1252                                loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
1253                                loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
1254                                msf_val = sony_toc->tracks[track_idx].track_start_msf;
1255                        }
1256
1257                        /* Logical buffer address or MSF format requested? */
1258                        if (loc_entry.cdte_format == CDROM_LBA) {
1259                                loc_entry.cdte_addr.lba = msf_to_log(msf_val);
1260                        } else if (loc_entry.cdte_format == CDROM_MSF) {
1261                                loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
1262                                loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
1263                                loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
1264                        }
1265                        copy_to_user(entry, &loc_entry, sizeof *entry);
1266                }
1267                return 0;
1268                break;
1269
1270        case CDROMPLAYTRKIND:           /* Play a track.  This currently ignores index. */
1271                {
1272                        struct cdrom_ti ti;
1273                        int track_idx;
1274
1275                        sony_get_toc();
1276                        if (!sony_toc_read)
1277                                return -EIO;
1278                        err = verify_area(VERIFY_READ, (char *)arg, sizeof ti);
1279                        if (err)
1280                                return err;
1281
1282                        copy_from_user(&ti, (char *)arg, sizeof ti);
1283                        if ((ti.cdti_trk0 < sony_toc->first_track_num)
1284                                || (sony_toc->last_track_num < ti.cdti_trk0)
1285                                || (ti.cdti_trk1 < ti.cdti_trk0)) {
1286                                return -EINVAL;
1287                        }
1288                        track_idx = find_track(int_to_bcd(ti.cdti_trk0));
1289                        if (track_idx < 0)
1290                                return -EINVAL;
1291                        params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
1292                        params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
1293                        params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
1294                        /*
1295                         * If we want to stop after the last track, use the lead-out
1296                         * MSF to do that.
1297                         */
1298                        if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
1299                                log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
1300                                                   &(params[4]));
1301                        } else {
1302                                track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
1303                                if (track_idx < 0)
1304                                        return -EINVAL;
1305                                log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
1306                                                   &(params[4]));
1307                        }
1308                        params[0] = 0x03;
1309
1310                        spin_up_drive(status);
1311
1312                        set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1313
1314                        /* Start the drive at the saved position. */
1315                        cmd_buff[0] = SONY535_PLAY_AUDIO;
1316                        cmd_buff[1] = 0;        /* play back starting at this address */
1317                        cmd_buff[2] = params[1];
1318                        cmd_buff[3] = params[2];
1319                        cmd_buff[4] = params[3];
1320                        cmd_buff[5] = SONY535_PLAY_AUDIO;
1321                        cmd_buff[6] = 2;        /* set ending address */
1322                        cmd_buff[7] = params[4];
1323                        cmd_buff[8] = params[5];
1324                        cmd_buff[9] = params[6];
1325                        if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1326                                (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1327                                printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
1328                                                status[0]);
1329                                printk("... Params: %x %x %x %x %x %x %x\n",
1330                                                params[0], params[1], params[2],
1331                                                params[3], params[4], params[5], params[6]);
1332                                return -EIO;
1333                        }
1334                        /* Save the final position for pauses and resumes */
1335                        final_pos_msf[0] = params[4];
1336                        final_pos_msf[1] = params[5];
1337                        final_pos_msf[2] = params[6];
1338                        sony_audio_status = CDROM_AUDIO_PLAY;
1339                        return 0;
1340                }
1341
1342        case CDROMSUBCHNL:                      /* Get subchannel info */
1343                return sony_get_subchnl_info(arg);
1344
1345        case CDROMVOLCTRL:                      /* Volume control.  What volume does this change, anyway? */
1346                {
1347                        struct cdrom_volctrl volctrl;
1348
1349                        err = verify_area(VERIFY_READ, (char *)arg, sizeof volctrl);
1350                        if (err)
1351                                return err;
1352
1353                        copy_from_user(&volctrl, (char *)arg, sizeof volctrl);
1354                        cmd_buff[0] = SONY535_SET_VOLUME;
1355                        cmd_buff[1] = volctrl.channel0;
1356                        cmd_buff[2] = volctrl.channel1;
1357                        if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
1358                                printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
1359                                                status[0]);
1360                                return -EIO;
1361                        }
1362                }
1363                return 0;
1364
1365        case CDROMEJECT:                        /* Eject the drive */
1366                cmd_buff[0] = SONY535_STOP;
1367                do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1368                cmd_buff[0] = SONY535_SPIN_DOWN;
1369                do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1370
1371                sony_audio_status = CDROM_AUDIO_INVALID;
1372                cmd_buff[0] = SONY535_EJECT_CADDY;
1373                if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1374                        printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
1375                                        status[0]);
1376                        return -EIO;
1377                }
1378                return 0;
1379                break;
1380
1381        default:
1382                return -EINVAL;
1383        }
1384}
1385
1386
1387/*
1388 * Open the drive for operations.  Spin the drive up and read the table of
1389 * contents if these have not already been done.
1390 */
1391static int
1392cdu_open(struct inode *inode,
1393                 struct file *filp)
1394{
1395        Byte status[2], cmd_buff[2];
1396
1397        if (sony_inuse)
1398                return -EBUSY;
1399        if (check_drive_status() != 0)
1400                return -EIO;
1401        sony_inuse = 1;
1402
1403        if (spin_up_drive(status) != 0) {
1404                printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
1405                                status[0]);
1406                sony_inuse = 0;
1407                return -EIO;
1408        }
1409        sony_get_toc();
1410        if (!sony_toc_read) {
1411                cmd_buff[0] = SONY535_SPIN_DOWN;
1412                do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1413                sony_inuse = 0;
1414                return -EIO;
1415        }
1416        if (inode) {
1417                check_disk_change(inode->i_rdev);
1418        }
1419        sony_usage++;
1420
1421#ifdef LOCK_DOORS
1422        /* disable the eject button while mounted */
1423        cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
1424        do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1425#endif
1426
1427        return 0;
1428}
1429
1430
1431/*
1432 * Close the drive.  Spin it down if no task is using it.  The spin
1433 * down will fail if playing audio, so audio play is OK.
1434 */
1435static int
1436cdu_release(struct inode *inode,
1437                        struct file *filp)
1438{
1439        Byte status[2], cmd_no;
1440
1441        sony_inuse = 0;
1442
1443        if (0 < sony_usage) {
1444                sony_usage--;
1445        }
1446        if (sony_usage == 0) {
1447                check_drive_status();
1448
1449                if (sony_audio_status != CDROM_AUDIO_PLAY) {
1450                        cmd_no = SONY535_SPIN_DOWN;
1451                        do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1452                }
1453#ifdef LOCK_DOORS
1454                /* enable the eject button after umount */
1455                cmd_no = SONY535_ENABLE_EJECT_BUTTON;
1456                do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1457#endif
1458        }
1459        return 0;
1460}
1461
1462static struct block_device_operations cdu_fops =
1463{
1464        owner:                  THIS_MODULE,
1465        open:                   cdu_open,
1466        release:                cdu_release,
1467        ioctl:                  cdu_ioctl,
1468        check_media_change:     cdu535_check_media_change,
1469};
1470
1471static int sonycd535_block_size = CDU535_BLOCK_SIZE;
1472
1473/*
1474 * Initialize the driver.
1475 */
1476int __init 
1477sony535_init(void)
1478{
1479        struct s535_sony_drive_config drive_config;
1480        Byte cmd_buff[3];
1481        Byte ret_buff[2];
1482        Byte status[2];
1483        unsigned long snap;
1484        int  got_result = 0;
1485        int  tmp_irq;
1486        int  i;
1487
1488        /* Setting the base I/O address to 0 will disable it. */
1489        if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
1490                return 0;
1491
1492        /* Set up all the register locations */
1493        result_reg = sony535_cd_base_io;
1494        command_reg = sony535_cd_base_io;
1495        data_reg = sony535_cd_base_io + 1;
1496        read_status_reg = sony535_cd_base_io + 2;
1497        select_unit_reg = sony535_cd_base_io + 3;
1498
1499#ifndef USE_IRQ
1500        sony535_irq_used = 0;   /* polling only until this is ready... */
1501#endif
1502        /* we need to poll until things get initialized */
1503        tmp_irq = sony535_irq_used;
1504        sony535_irq_used = 0;
1505
1506#if DEBUG > 0
1507        printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
1508                        sony535_cd_base_io);
1509#endif
1510        if (check_region(sony535_cd_base_io,4)) {
1511                printk(CDU535_MESSAGE_NAME ": my base address is not free!\n");
1512                return -EIO;
1513        }
1514
1515        /* look for the CD-ROM, follows the procedure in the DOS driver */
1516        inb(select_unit_reg);
1517        /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
1518        current->state = TASK_INTERRUPTIBLE;
1519        schedule_timeout((HZ+17)*40/18);
1520        inb(result_reg);
1521
1522        outb(0, read_status_reg);       /* does a reset? */
1523        snap = jiffies;
1524        while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
1525                select_unit(0);
1526                if (inb(result_reg) != 0xff) {
1527                        got_result = 1;
1528                        break;
1529                }
1530                sony_sleep();
1531        }
1532
1533        if (got_result && (check_drive_status() != TIME_OUT)) {
1534                /* CD-ROM drive responded --  get the drive configuration */
1535                cmd_buff[0] = SONY535_INQUIRY;
1536                if (do_sony_cmd(cmd_buff, 1, status,
1537                                                (Byte *)&drive_config, 28, 1) == 0) {
1538                        /* was able to get the configuration,
1539                         * set drive mode as rest of init
1540                         */
1541#if DEBUG > 0
1542                        /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
1543                        if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
1544                                printk(CDU535_MESSAGE_NAME
1545                                                "Inquiry command returned status = 0x%x\n", status[0]);
1546#endif
1547                        /* now ready to use interrupts, if available */
1548                        sony535_irq_used = tmp_irq;
1549#ifndef MODULE
1550/* This code is not in MODULEs by default, since the autoirq stuff might
1551 * not be in the module-accessible symbol table.
1552 */
1553                        /* A negative sony535_irq_used will attempt an autoirq. */
1554                        if (sony535_irq_used < 0) {
1555                                autoirq_setup(0);
1556                                enable_interrupts();
1557                                outb(0, read_status_reg);       /* does a reset? */
1558                                sony535_irq_used = autoirq_report(10);
1559                                disable_interrupts();
1560                        }
1561#endif
1562                        if (sony535_irq_used > 0) {
1563                            if (request_irq(sony535_irq_used, cdu535_interrupt,
1564                                                                SA_INTERRUPT, CDU535_HANDLE, NULL)) {
1565                                        printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
1566                                                        " driver; polling instead.\n", sony535_irq_used);
1567                                        sony535_irq_used = 0;
1568                                }
1569                        }
1570                        cmd_buff[0] = SONY535_SET_DRIVE_MODE;
1571                        cmd_buff[1] = 0x0;      /* default audio */
1572                        if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
1573                                /* set the drive mode successful, we are set! */
1574                                sony_buffer_size = SONY535_BUFFER_SIZE;
1575                                sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
1576
1577                                printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
1578                                           drive_config.vendor_id,
1579                                           drive_config.product_id,
1580                                           drive_config.product_rev_level);
1581                                printk("  base address %03X, ", sony535_cd_base_io);
1582                                if (tmp_irq > 0)
1583                                        printk("IRQ%d, ", tmp_irq);
1584                                printk("using %d byte buffer\n", sony_buffer_size);
1585
1586                                devfs_register (NULL, CDU535_HANDLE,
1587                                                DEVFS_FL_DEFAULT,
1588                                                MAJOR_NR, 0,
1589                                                S_IFBLK | S_IRUGO | S_IWUGO,
1590                                                &cdu_fops, NULL);
1591                                if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
1592                                        printk("Unable to get major %d for %s\n",
1593                                                        MAJOR_NR, CDU535_MESSAGE_NAME);
1594                                        return -EIO;
1595                                }
1596                                blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1597                                blksize_size[MAJOR_NR] = &sonycd535_block_size;
1598                                read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read-ahead */
1599
1600                                sony_toc = (struct s535_sony_toc *)
1601                                        kmalloc(sizeof *sony_toc, GFP_KERNEL);
1602                                if (sony_toc == NULL) {
1603                                        blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1604                                        return -ENOMEM;
1605                                }
1606                                last_sony_subcode = (struct s535_sony_subcode *)
1607                                        kmalloc(sizeof *last_sony_subcode, GFP_KERNEL);
1608                                if (last_sony_subcode == NULL) {
1609                                        blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1610                                        kfree(sony_toc);
1611                                        return -ENOMEM;
1612                                }
1613                                sony_buffer = (Byte **)
1614                                        kmalloc(4 * sony_buffer_sectors, GFP_KERNEL);
1615                                if (sony_buffer == NULL) {
1616                                        blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1617                                        kfree(sony_toc);
1618                                        kfree(last_sony_subcode);
1619                                        return -ENOMEM;
1620                                }
1621                                for (i = 0; i < sony_buffer_sectors; i++) {
1622                                        sony_buffer[i] =
1623                                                                (Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
1624                                        if (sony_buffer[i] == NULL) {
1625                                                while (--i>=0)
1626                                                        kfree(sony_buffer[i]);
1627                                                blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1628                                                kfree(sony_buffer);
1629                                                kfree(sony_toc);
1630                                                kfree(last_sony_subcode);
1631                                                return -ENOMEM;
1632                                        }
1633                                }
1634                                initialized = 1;
1635                        }
1636                }
1637        }
1638
1639        if (!initialized) {
1640                printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
1641                return -EIO;
1642        }
1643        request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
1644        register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &cdu_fops, 0);
1645        return 0;
1646}
1647
1648#ifndef MODULE
1649
1650/*
1651 * accept "kernel command line" parameters
1652 * (added by emoenke@gwdg.de)
1653 *
1654 * use: tell LILO:
1655 *                 sonycd535=0x320
1656 *
1657 * the address value has to be the existing CDROM port address.
1658 */
1659static int __init
1660sonycd535_setup(char *strings)
1661{
1662        int ints[3];
1663        (void)get_options(strings, ARRAY_SIZE(ints), ints);
1664        /* if IRQ change and default io base desired,
1665         * then call with io base of 0
1666         */
1667        if (ints[0] > 0)
1668                if (ints[1] != 0)
1669                        sony535_cd_base_io = ints[1];
1670        if (ints[0] > 1)
1671                sony535_irq_used = ints[2];
1672        if ((strings != NULL) && (*strings != '\0'))
1673                printk(CDU535_MESSAGE_NAME
1674                                ": Warning: Unknown interface type: %s\n", strings);
1675                                
1676        return 1;
1677}
1678
1679__setup("sonycd535=", sonycd535_setup);
1680
1681#endif /* MODULE */
1682
1683void __exit
1684sony535_exit(void)
1685{
1686        int i;
1687
1688        release_region(sony535_cd_base_io, 4);
1689        for (i = 0; i < sony_buffer_sectors; i++)
1690                kfree(sony_buffer[i]);
1691        kfree(sony_buffer);
1692        kfree(last_sony_subcode);
1693        kfree(sony_toc);
1694        devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0,
1695                                           DEVFS_SPECIAL_BLK, 0));
1696        if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
1697                printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
1698        else
1699                printk(KERN_INFO CDU535_HANDLE " module released\n");
1700}
1701
1702#ifdef MODULE
1703module_init(sony535_init);
1704#endif
1705module_exit(sony535_exit);
1706
1707
1708MODULE_LICENSE("GPL");
1709
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.