root/drivers/block/sonycd535.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdu535_check_media_change
  2. sony_sleep
  3. select_unit
  4. read_result_reg
  5. read_exec_status
  6. check_drive_status
  7. do_sony_cmd
  8. set_drive_mode
  9. seek_and_read_N_blocks
  10. request_toc_data
  11. spin_up_drive
  12. int_to_bcd
  13. bcd_to_int
  14. log_to_msf
  15. msf_to_log
  16. size_to_buf
  17. do_cdu535_request
  18. sony_get_toc
  19. find_track
  20. read_subcode
  21. sony_get_subchnl_info
  22. cdu_ioctl
  23. cdu_open
  24. cdu_release
  25. sony535_init
  26. sonycd535_setup
  27. cleanup_module

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

/* [previous][next][first][last][top][bottom][index][help] */