root/kernel/blk_drv/cdu31a.c

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

DEFINITIONS

This source file includes following definitions.
  1. check_cdu31a_media_change
  2. sony_sleep
  3. is_attention
  4. is_busy
  5. is_data_ready
  6. is_data_requested
  7. is_result_ready
  8. is_param_write_rdy
  9. reset_drive
  10. clear_attention
  11. clear_result_ready
  12. clear_data_ready
  13. clear_param_reg
  14. read_status_register
  15. read_result_register
  16. read_data_register
  17. write_param
  18. write_cmd
  19. write_params
  20. get_result
  21. get_data
  22. do_sony_cd_cmd
  23. handle_sony_cd_attention
  24. int_to_bcd
  25. bcd_to_int
  26. log_to_msf
  27. msf_to_log
  28. size_to_buf
  29. do_cdu31a_request
  30. sony_get_toc
  31. find_track
  32. read_subcode
  33. sony_get_subchnl_info
  34. scd_ioctl
  35. scd_open
  36. scd_release
  37. get_drive_configuration
  38. cdu31a_init

   1 /*
   2  * Sony CDU-31A CDROM interface device driver.
   3  *
   4  * Corey Minyard (minyard@wf-rch.cirr.com)
   5  *
   6  * Colossians 3:17
   7  *
   8  * The Sony interface device driver handles Sony interface CDROM
   9  * drives and provides a complete block-level interface as well as an
  10  * ioctl() interface compatible with the Sun (as specified in
  11  * include/linux/cdrom.h).  With this interface, CDROMs can be
  12  * accessed and standard audio CDs can be played back normally.
  13  *
  14  * This interface is (unfortunatly) a polled interface.  This is
  15  * because most Sony interfaces are set up with DMA and interrupts
  16  * disables.  Some (like mine) do not even have the capability to
  17  * handle interrupts or DMA.  For this reason you will see a lot of
  18  * the following:
  19  *
  20  *   retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
  21  *   while ((retry_count > jiffies) && (! <some condition to wait for))
  22  *   {
  23  *      while (handle_sony_cd_attention())
  24  *         ;
  25  *
  26  *      sony_sleep();
  27  *   }
  28  *   if (the condition not met)
  29  *   {
  30  *      return an error;
  31  *   }
  32  *
  33  * This ugly hack waits for something to happen, sleeping a little
  34  * between every try.  it also handles attentions, which are
  35  * asyncronous events from the drive informing the driver that a disk
  36  * has been inserted, removed, etc.
  37  *
  38  * One thing about these drives: They talk in MSF (Minute Second Frame) format.
  39  * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
  40  * disk.  The funny thing is that these are sent to the drive in BCD, but the
  41  * interface wants to see them in decimal.  A lot of conversion goes on.
  42  *
  43  *  Copyright (C) 1993  Corey Minyard
  44  *
  45  *  This program is free software; you can redistribute it and/or modify
  46  *  it under the terms of the GNU General Public License as published by
  47  *  the Free Software Foundation; either version 2 of the License, or
  48  *  (at your option) any later version.
  49  *
  50  *  This program is distributed in the hope that it will be useful,
  51  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  52  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  53  *  GNU General Public License for more details.
  54  *
  55  *  You should have received a copy of the GNU General Public License
  56  *  along with this program; if not, write to the Free Software
  57  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  58  *
  59  */
  60 
  61 
  62 #include <linux/config.h>
  63 #ifdef CONFIG_CDU31A
  64 
  65 #include <linux/errno.h>
  66 #include <linux/signal.h>
  67 #include <linux/sched.h>
  68 #include <linux/timer.h>
  69 #include <linux/fs.h>
  70 #include <linux/kernel.h>
  71 #include <linux/hdreg.h>
  72 #include <linux/genhd.h>
  73 
  74 #include <asm/system.h>
  75 #include <asm/io.h>
  76 #include <asm/segment.h>
  77 
  78 #include <linux/cdrom.h>
  79 #include <linux/cdu31a.h>
  80 
  81 #define MAJOR_NR 15
  82 #include "blk.h"
  83 
  84 
  85 static unsigned short cdu31a_addresses[] =
  86 {
  87    0x340,       /* Standard configuration Sony Interface */
  88    0x1f88,      /* Fusion CD-16 */
  89    0x360,       /* Secondary standard Sony Interface */
  90    0x320,       /* Secondary standard Sony Interface */
  91    0x330,       /* Secondary standard Sony Interface */
  92    0
  93 };
  94 
  95 
  96 static int handle_sony_cd_attention(void);
  97 static int read_subcode(void);
  98 static void sony_get_toc(void);
  99 static int scd_open(struct inode *inode, struct file *filp);
 100 
 101 
 102 /* The base I/O address of the Sony Interface.  This is a variable (not a
 103    #define) so it can be easily changed via some future ioctl() */
 104 static unsigned short sony_cd_base_io = 0;
 105 
 106 /*
 107  * The following are I/O addresses of the various registers for the drive.  The
 108  * comment for the base address also applies here.
 109  */
 110 static volatile unsigned short sony_cd_cmd_reg;
 111 static volatile unsigned short sony_cd_param_reg;
 112 static volatile unsigned short sony_cd_write_reg;
 113 static volatile unsigned short sony_cd_control_reg;
 114 static volatile unsigned short sony_cd_status_reg;
 115 static volatile unsigned short sony_cd_result_reg;
 116 static volatile unsigned short sony_cd_read_reg;
 117 static volatile unsigned short sony_cd_fifost_reg;
 118 
 119 
 120 static int initialized = 0;                /* Has the drive been initialized? */
 121 static int sony_disc_changed = 1;          /* Has the disk been changed
 122                                               since the last check? */
 123 static int sony_toc_read = 0;              /* Has the table of contents been
 124                                               read? */
 125 static int sony_spun_up = 0;               /* Has the drive been spun up? */
 126 static unsigned int sony_buffer_size;      /* Size in bytes of the read-ahead
 127                                               buffer. */
 128 static unsigned int sony_buffer_sectors;   /* Size (in 2048 byte records) of
 129                                               the read-ahead buffer. */
 130 static unsigned int sony_usage = 0;        /* How many processes have the
 131                                               drive open. */
 132 
 133 static volatile int sony_first_block = -1; /* First OS block (512 byte) in
 134                                               the read-ahead buffer */
 135 static volatile int sony_last_block = -1;  /* Last OS block (512 byte) in
 136                                               the read-ahead buffer */
 137 
 138 static struct s_sony_toc *sony_toc;              /* Points to the table of
 139                                                     contents. */
 140 static struct s_sony_subcode * volatile last_sony_subcode; /* Points to the last
 141                                                     subcode address read */
 142 static unsigned char * volatile sony_buffer;     /* Points to the read-ahead
 143                                                     buffer */
 144 
 145 static volatile int sony_inuse = 0;  /* Is the drive in use?  Only one operation at a time
 146                                         allowed */
 147 
 148 static struct wait_queue * sony_wait = NULL;
 149 
 150 static struct task_struct *has_cd_task = NULL;  /* The task that is currently using the
 151                                                    CDROM drive, or NULL if none. */
 152 
 153 /*
 154  * The audio status uses the values from read subchannel data as specified
 155  * in include/linux/cdrom.h.
 156  */
 157 static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
 158 
 159 /*
 160  * The following are a hack for pausing and resuming audio play.  The drive
 161  * does not work as I would expect it, if you stop it then start it again,
 162  * the drive seeks back to the beginning and starts over.  This holds the
 163  * position during a pause so a resume can restart it.  It uses the
 164  * audio status variable above to tell if it is paused.
 165  */
 166 unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
 167 unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
 168 
 169 /*
 170  * This routine returns 1 if the disk has been changed since the last
 171  * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
 172  */
 173 int
 174 check_cdu31a_media_change(int full_dev, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176    int retval, target;
 177 
 178 
 179    target = MINOR(full_dev);
 180 
 181    if (target > 0) {
 182       printk("Sony CD-ROM request error: invalid device.\n");
 183       return 0;
 184    }
 185 
 186    retval = sony_disc_changed;
 187    if (!flag)
 188    {
 189       sony_disc_changed = 0;
 190    }
 191 
 192    return retval;
 193 }
 194 
 195 
 196 /*
 197  * Wait a little while (used for polling the drive).  If in initialization,
 198  * setting a timeout doesn't work, so just loop for a while.
 199  */
 200 static inline void
 201 sony_sleep(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203    current->state = TASK_INTERRUPTIBLE;
 204    current->timeout = jiffies;
 205    schedule();
 206 }
 207 
 208 
 209 /*
 210  * The following are convenience routine to read various status and set
 211  * various conditions in the drive.
 212  */
 213 static inline int
 214 is_attention(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216    return((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0);
 217 }
 218 
 219 static inline int
 220 is_busy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222    return((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0);
 223 }
 224 
 225 static inline int
 226 is_data_ready(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228    return((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0);
 229 }
 230 
 231 static inline int
 232 is_data_requested(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234    return((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0);
 235 }
 236 
 237 static inline int
 238 is_result_ready(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240    return((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0);
 241 }
 242 
 243 static inline int
 244 is_param_write_rdy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 245 {
 246    return((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0);
 247 }
 248 
 249 static inline void
 250 reset_drive(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 251 {
 252    outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
 253 }
 254 
 255 static inline void
 256 clear_attention(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258    outb(SONY_ATTN_CLR_BIT, sony_cd_control_reg);
 259 }
 260 
 261 static inline void
 262 clear_result_ready(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264    outb(SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
 265 }
 266 
 267 static inline void
 268 clear_data_ready(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 269 {
 270    outb(SONY_DATA_RDY_CLR_BIT, sony_cd_control_reg);
 271 }
 272 
 273 static inline void
 274 clear_param_reg(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 275 {
 276    outb(SONY_PARAM_CLR_BIT, sony_cd_control_reg);
 277 }
 278 
 279 static inline unsigned char
 280 read_status_register(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282    return(inb(sony_cd_status_reg));
 283 }
 284 
 285 static inline unsigned char
 286 read_result_register(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 287 {
 288    return(inb(sony_cd_result_reg));
 289 }
 290 
 291 static inline unsigned char
 292 read_data_register(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294    return(inb(sony_cd_read_reg));
 295 }
 296 
 297 static inline void
 298 write_param(unsigned char param)
     /* [previous][next][first][last][top][bottom][index][help] */
 299 {
 300    outb(param, sony_cd_param_reg);
 301 }
 302 
 303 static inline void
 304 write_cmd(unsigned char cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306    outb(cmd, sony_cd_cmd_reg);
 307    outb(SONY_RES_RDY_INT_EN_BIT, sony_cd_control_reg);
 308 }
 309 
 310 
 311 /*
 312  * This routine writes data to the parameter register.  Since this should
 313  * happen fairly fast, it is polled with no OS waits between.
 314  */
 315 static int
 316 write_params(unsigned char *params,
     /* [previous][next][first][last][top][bottom][index][help] */
 317              int num_params)
 318 {
 319    unsigned int retry_count;
 320 
 321 
 322    retry_count = SONY_READY_RETRIES;
 323    while ((retry_count > 0) && (!is_param_write_rdy()))
 324    {
 325       retry_count--;
 326    }
 327    if (!is_param_write_rdy())
 328    {
 329       return -EIO;
 330    }
 331 
 332    while (num_params > 0)
 333    {
 334       write_param(*params);
 335       params++;
 336       num_params--;
 337    }
 338 
 339    return 0;
 340 }
 341 
 342 
 343 /*
 344  * The following reads data from the command result register.  It is a
 345  * fairly complex routine, all status info flows back through this
 346  * interface.  The algorithm is stolen directly from the flowcharts in
 347  * the drive manual.
 348  */
 349 static void
 350 get_result(unsigned char *result_buffer,
     /* [previous][next][first][last][top][bottom][index][help] */
 351            unsigned int *result_size)
 352 {
 353    unsigned char a, b;
 354    int i;
 355    unsigned int retry_count;
 356 
 357 
 358    while (handle_sony_cd_attention())
 359       ;
 360    /* Wait for the result data to be ready */
 361    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 362    while ((retry_count > jiffies) && (is_busy() || (!(is_result_ready()))))
 363    {
 364       sony_sleep();
 365 
 366       while (handle_sony_cd_attention())
 367          ;
 368    }
 369    if (is_busy() || (!(is_result_ready())))
 370    {
 371       result_buffer[0] = 0x20;
 372       result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 373       *result_size = 2;
 374       return;
 375    }
 376 
 377    /*
 378     * Get the first two bytes.  This determines what else needs
 379     * to be done.
 380     */
 381    clear_result_ready();
 382    a = read_result_register();
 383    *result_buffer = a;
 384    result_buffer++;
 385    b = read_result_register();
 386    *result_buffer = b;
 387    result_buffer++;
 388    *result_size = 2;
 389 
 390    /*
 391     * 0x20 means an error occured.  Byte 2 will have the error code.
 392     * Otherwise, the command succeded, byte 2 will have the count of
 393     * how many more status bytes are coming.
 394     *
 395     * The result register can be read 10 bytes at a time, a wait for
 396     * result ready to be asserted must be done between every 10 bytes.
 397     */
 398    if ((a & 0xf0) != 0x20)
 399    {
 400       if (b > 8)
 401       {
 402          for (i=0; i<8; i++)
 403          {
 404             *result_buffer = read_result_register();
 405             result_buffer++;
 406             (*result_size)++;
 407          }
 408          b = b - 8;
 409 
 410          while (b > 10)
 411          {
 412             retry_count = SONY_READY_RETRIES;
 413             while ((retry_count > 0) && (!is_result_ready()))
 414             {
 415                retry_count--;
 416             }
 417             if (!is_result_ready())
 418             {
 419                result_buffer[0] = 0x20;
 420                result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 421                *result_size = 2;
 422                return;
 423             }
 424 
 425             clear_result_ready();
 426                                 
 427             for (i=0; i<10; i++)
 428             {
 429                *result_buffer = read_result_register();
 430                result_buffer++;
 431                (*result_size)++;
 432             }
 433             b = b - 10;
 434          }
 435 
 436          if (b > 0)
 437          {
 438             retry_count = SONY_READY_RETRIES;
 439             while ((retry_count > 0) && (!is_result_ready()))
 440             {
 441                retry_count--;
 442             }
 443             if (!is_result_ready())
 444             {
 445                result_buffer[0] = 0x20;
 446                result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 447                *result_size = 2;
 448                return;
 449             }
 450          }
 451       }
 452 
 453       while (b > 0)
 454       {
 455          *result_buffer = read_result_register();
 456          result_buffer++;
 457          (*result_size)++;
 458          b--;
 459       }
 460    }
 461 }
 462 
 463 
 464 /*
 465  * This routine issues a read data command and gets the data.  I don't
 466  * really like the way this is done (I would prefer for do_sony_cmd() to
 467  * handle it automatically) but I found that the drive returns status
 468  * when it finishes reading (not when the host has read all the data)
 469  * or after it gets an error.  This means that the status can be
 470  * received at any time and should be handled immediately (at least
 471  * between every 2048 byte block) to check for errors, we can't wait
 472  * until all the data is read.
 473  */
 474 static void
 475 get_data(unsigned char *data,
     /* [previous][next][first][last][top][bottom][index][help] */
 476          unsigned char *params,         /* 6 bytes with the MSF start address
 477                                            and number of sectors to read. */
 478          unsigned int data_size,
 479          unsigned char *result_buffer,
 480          unsigned int *result_size)
 481 {
 482    int i;
 483    unsigned int cur_offset;
 484    unsigned int retry_count;
 485    int result_read;
 486    int num_retries;
 487 
 488 
 489    cli();
 490    if (current != has_cd_task) /* Allow recursive calls to this routine */
 491    {
 492       while (sony_inuse)
 493       {
 494          interruptible_sleep_on(&sony_wait);
 495          if (current->signal & ~current->blocked)
 496          {
 497             result_buffer[0] = 0x20;
 498             result_buffer[1] = SONY_SIGNAL_OP_ERR;
 499             *result_size = 2;
 500             return;
 501          }
 502       }
 503    }
 504    sony_inuse = 1;
 505    has_cd_task = current;
 506    sti();
 507 
 508    num_retries = 0;
 509 retry_data_operation:
 510 
 511    /*
 512     * Clear any outstanding attentions and wait for the drive to
 513     * complete any pending operations.
 514     */
 515    while (handle_sony_cd_attention())
 516       ;
 517 
 518    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 519    while ((retry_count > jiffies) && (is_busy()))
 520    {
 521       sony_sleep();
 522       
 523       while (handle_sony_cd_attention())
 524          ;
 525    }
 526    if (is_busy())
 527    {
 528       result_buffer[0] = 0x20;
 529       result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 530       *result_size = 2;
 531       goto get_data_end;
 532    }
 533 
 534    /* Issue the command */
 535    clear_result_ready();
 536    clear_param_reg();
 537 
 538    write_params(params, 6);
 539    write_cmd(SONY_READ_CMD);
 540 
 541    /*
 542     * Read the data from the drive one 2048 byte sector at a time.  Handle
 543     * any results received between sectors, if an error result is returned
 544     * terminate the operation immediately.
 545     */
 546    cur_offset = 0;
 547    result_read = 0;
 548    while (data_size > 0)
 549    {
 550       /* Wait for the drive to tell us we have something */
 551       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 552       while ((retry_count > jiffies) && (!(is_result_ready() || is_data_ready())))
 553       {
 554          while (handle_sony_cd_attention())
 555             ;
 556          
 557          sony_sleep();
 558       }
 559       if (!(is_result_ready() || is_data_ready()))
 560       {
 561          result_buffer[0] = 0x20;
 562          result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 563          *result_size = 2;
 564          goto get_data_end;
 565       }
 566       
 567       /* Handle results first */
 568       if (is_result_ready())
 569       {
 570          result_read = 1;
 571          get_result(result_buffer, result_size);
 572          if ((*result_size < 2) || (result_buffer[0] != 0))
 573          {
 574             goto get_data_end;
 575          }
 576       }
 577       else /* Handle data next */
 578       {
 579          /*
 580           * The drive has to be polled for status on a byte-by-byte basis
 581           * to know if the data is ready.  Yuck.  I really wish I could use DMA.
 582           */
 583          clear_data_ready();
 584          for (i=0; i<2048; i++)
 585          {
 586             retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 587             while ((retry_count > jiffies) && (!is_data_requested()))
 588             {
 589                while (handle_sony_cd_attention())
 590                   ;
 591                
 592                sony_sleep();
 593             }
 594             if (!is_data_requested())
 595             {
 596                result_buffer[0] = 0x20;
 597                result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 598                *result_size = 2;
 599                goto get_data_end;
 600             }
 601             
 602             *data = read_data_register();
 603             data++;
 604             data_size--;
 605          }
 606          cur_offset = cur_offset + 2048;
 607       }
 608    }
 609 
 610    /* Make sure the result has been read */
 611    if (!result_read)
 612    {
 613       get_result(result_buffer, result_size);
 614    }
 615 
 616 get_data_end:
 617    if (   ((result_buffer[0] & 0x20) == 0x20)
 618        && (num_retries < MAX_CDU31A_RETRIES))
 619    {
 620       num_retries++;
 621       goto retry_data_operation;
 622    }
 623 
 624    has_cd_task = NULL;
 625    sony_inuse = 0;
 626    wake_up_interruptible(&sony_wait);
 627 }
 628 
 629 
 630 /*
 631  * Do a command that does not involve data transfer.
 632  */
 633 static void
 634 do_sony_cd_cmd(unsigned char cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
 635                unsigned char *params,
 636                unsigned int num_params,
 637                unsigned char *result_buffer,
 638                unsigned int *result_size)
 639 {
 640    unsigned int retry_count;
 641    int num_retries;
 642 
 643 
 644    cli();
 645    if (current != has_cd_task) /* Allow recursive calls to this routine */
 646    {
 647       while (sony_inuse)
 648       {
 649          interruptible_sleep_on(&sony_wait);
 650          if (current->signal & ~current->blocked)
 651          {
 652             result_buffer[0] = 0x20;
 653             result_buffer[1] = SONY_SIGNAL_OP_ERR;
 654             *result_size = 2;
 655             return;
 656          }
 657       }
 658    }
 659    sony_inuse = 1;
 660    has_cd_task = current;
 661    sti();
 662 
 663    num_retries = 0;
 664 retry_cd_operation:
 665 
 666    while (handle_sony_cd_attention())
 667       ;
 668    
 669    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 670    while ((retry_count > jiffies) && (is_busy()))
 671    {
 672       sony_sleep();
 673       
 674       while (handle_sony_cd_attention())
 675          ;
 676    }
 677    if (is_busy())
 678    {
 679       result_buffer[0] = 0x20;
 680       result_buffer[1] = SONY_TIMEOUT_OP_ERR;
 681       *result_size = 2;
 682       goto do_cmd_end;
 683    }
 684 
 685    clear_result_ready();
 686    clear_param_reg();
 687 
 688    write_params(params, num_params);
 689    write_cmd(cmd);
 690 
 691    get_result(result_buffer, result_size);
 692 
 693 do_cmd_end:
 694    if (   ((result_buffer[0] & 0x20) == 0x20)
 695        && (num_retries < MAX_CDU31A_RETRIES))
 696    {
 697       num_retries++;
 698       goto retry_cd_operation;
 699    }
 700 
 701    has_cd_task = NULL;
 702    sony_inuse = 0;
 703    wake_up_interruptible(&sony_wait);
 704 }
 705 
 706 
 707 /*
 708  * Handle an attention from the drive.  This will return 1 if it found one
 709  * or 0 if not (if one is found, the caller might want to call again).
 710  */
 711 static int
 712 handle_sony_cd_attention(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 713 {
 714    unsigned char atten_code;
 715    unsigned char res_reg[2];
 716    unsigned int res_size;
 717 
 718 
 719    if (is_attention())
 720    {
 721       clear_attention();
 722       atten_code = read_result_register();
 723 
 724       switch (atten_code)
 725       {
 726        /* Someone changed the CD.  Mark it as changed */
 727       case SONY_MECH_LOADED_ATTN:
 728          sony_disc_changed = 1;
 729          sony_toc_read = 0;
 730          sony_audio_status = CDROM_AUDIO_NO_STATUS;
 731          sony_first_block = -1;
 732          sony_last_block = -1;
 733          if (initialized)
 734          {
 735             do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
 736             sony_get_toc();
 737          }
 738          break;
 739 
 740       case SONY_AUDIO_PLAY_DONE_ATTN:
 741          sony_audio_status = CDROM_AUDIO_COMPLETED;
 742          read_subcode();
 743          break;
 744 
 745       case SONY_EJECT_PUSHED_ATTN:
 746          sony_audio_status = CDROM_AUDIO_INVALID;
 747          break;
 748 
 749       case SONY_LEAD_IN_ERR_ATTN:
 750       case SONY_LEAD_OUT_ERR_ATTN:
 751       case SONY_DATA_TRACK_ERR_ATTN:
 752       case SONY_AUDIO_PLAYBACK_ERR_ATTN:
 753          sony_audio_status = CDROM_AUDIO_ERROR;
 754          break;
 755       }
 756       return(1);
 757    }
 758 
 759    return(0);
 760 }
 761 
 762 
 763 /* Convert from an integer 0-99 to BCD */
 764 static inline unsigned int
 765 int_to_bcd(unsigned int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767    int retval;
 768 
 769 
 770    retval = (val / 10) << 4;
 771    retval = retval | val % 10;
 772    return(retval);
 773 }
 774 
 775 
 776 /* Convert from BCD to an integer from 0-99 */
 777 static unsigned int
 778 bcd_to_int(unsigned int bcd)
     /* [previous][next][first][last][top][bottom][index][help] */
 779 {
 780    return((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f));
 781 }
 782 
 783 
 784 /*
 785  * Convert a logical sector value (like the OS would want to use for
 786  * a block device) to an MSF format.
 787  */
 788 static void
 789 log_to_msf(unsigned int log, unsigned char *msf)
     /* [previous][next][first][last][top][bottom][index][help] */
 790 {
 791    log = log + LOG_START_OFFSET;
 792    msf[0] = int_to_bcd(log / 4500);
 793    log = log % 4500;
 794    msf[1] = int_to_bcd(log / 75);
 795    msf[2] = int_to_bcd(log % 75);
 796 }
 797 
 798 
 799 /*
 800  * Convert an MSF format to a logical sector.
 801  */
 802 static unsigned int
 803 msf_to_log(unsigned char *msf)
     /* [previous][next][first][last][top][bottom][index][help] */
 804 {
 805    unsigned int log;
 806 
 807 
 808    log = bcd_to_int(msf[2]);
 809    log += bcd_to_int(msf[1]) * 75;
 810    log += bcd_to_int(msf[0]) * 4500;
 811    log = log - LOG_START_OFFSET;
 812 
 813    return log;
 814 }
 815 
 816 
 817 /*
 818  * Take in integer size value and put it into a buffer like
 819  * the drive would want to see a number-of-sector value.
 820  */
 821 static void
 822 size_to_buf(unsigned int size,
     /* [previous][next][first][last][top][bottom][index][help] */
 823             unsigned char *buf)
 824 {
 825    buf[0] = size / 65536;
 826    size = size % 65536;
 827    buf[1] = size / 256;
 828    buf[2] = size % 256;
 829 }
 830 
 831 
 832 /*
 833  * The OS calls this to perform a read or write operation to the drive.
 834  * Write obviously fail.  Reads to a read ahead of sony_buffer_size
 835  * bytes to help speed operations.  This especially helps since the OS
 836  * uses 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
 837  * data access on a CD is done sequentially, this saves a lot of operations.
 838  */
 839 static void
 840 do_cdu31a_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 841 {
 842    int block;
 843    unsigned int dev;
 844    int nsect;
 845    unsigned char params[10];
 846    unsigned char res_reg[2];
 847    unsigned int res_size;
 848    int copyoff;
 849    int spin_up_retry;
 850    unsigned int read_size;
 851 
 852 
 853    if (!sony_spun_up)
 854    {
 855       scd_open (NULL,NULL);
 856    }
 857 
 858    while (1)
 859    {
 860       /*
 861        * The beginning here is stolen from the hard disk driver.  I hope
 862        * its right.
 863        */
 864       if (!(CURRENT) || CURRENT->dev < 0)
 865       {
 866          return;
 867       }
 868 
 869       INIT_REQUEST;
 870       dev = MINOR(CURRENT->dev);
 871       block = CURRENT->sector;
 872       nsect = CURRENT->nr_sectors;
 873       if (dev != 0)
 874       {
 875          end_request(0);
 876          continue;
 877       }
 878 
 879       switch(CURRENT->cmd)
 880       {
 881       case READ:
 882          /*
 883           * If the block address is invalid or the request goes beyond the end of
 884           * the media, return an error.
 885           */
 886          if ((block / 4) >= sony_toc->lead_out_start_lba)
 887          {
 888             end_request(0);
 889             return;
 890          }
 891          if (((block + nsect) / 4) >= sony_toc->lead_out_start_lba)
 892          {
 893             end_request(0);
 894             return;
 895          }
 896 
 897          while (nsect > 0)
 898          {
 899             /*
 900              * If the requested sector is not currently in the read-ahead buffer,
 901              * it must be read in.
 902              */
 903             if ((block < sony_first_block) || (block > sony_last_block))
 904             {
 905                sony_first_block = (block / 4) * 4;
 906                log_to_msf(block/4, params);
 907 
 908                /*
 909                 * If the full read-ahead would go beyond the end of the media, trim
 910                 * it back to read just till the end of the media.
 911                 */
 912                if (((block / 4) + sony_buffer_sectors) >= sony_toc->lead_out_start_lba)
 913                {
 914                   sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
 915                   read_size = sony_toc->lead_out_start_lba - (block / 4);
 916                }
 917                else
 918                {
 919                   sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
 920                   read_size = sony_buffer_sectors;
 921                }
 922                size_to_buf(read_size, &params[3]);
 923 
 924                /*
 925                 * Read the data.  If the drive was not spinning, spin it up and try
 926                 * once more.  I know, the goto is ugly, but I am too lazy to fix it.
 927                 */
 928                spin_up_retry = 0;
 929 try_read_again:
 930                get_data(sony_buffer, params, (read_size * 2048), res_reg, &res_size);
 931                if ((res_size < 2) || (res_reg[0] != 0))
 932                {
 933                   if ((res_reg[1] == SONY_NOT_SPIN_ERR) && (!spin_up_retry))
 934                   {
 935                      do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
 936                      spin_up_retry = 1;
 937                      goto try_read_again;
 938                   }
 939 
 940                   printk("Sony CDROM Read error: 0x%2.2x\n", res_reg[1]);
 941                   sony_first_block = -1;
 942                   sony_last_block = -1;
 943                   end_request(0);
 944                   return;
 945                }
 946             }
 947    
 948             /*
 949              * The data is in memory now, copy it to the buffer and advance to the
 950              * next block to read.
 951              */
 952             copyoff = (block - sony_first_block) * 512;
 953             memcpy(CURRENT->buffer, sony_buffer+copyoff, 512);
 954                
 955             block += 1;
 956             nsect -= 1;
 957             CURRENT->buffer += 512;
 958          }
 959                
 960          end_request(1);
 961          break;
 962             
 963       case WRITE:
 964          end_request(0);
 965          break;
 966             
 967       default:
 968          panic("Unkown SONY CD cmd");
 969       }
 970    }
 971 }
 972 
 973 
 974 /*
 975  * Read the table of contents from the drive and set sony_toc_read if
 976  * successful.
 977  */
 978 static void
 979 sony_get_toc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 980 {
 981    unsigned int res_size;
 982 
 983 
 984    if (!sony_toc_read)
 985    {
 986       do_sony_cd_cmd(SONY_REQ_TOC_DATA_CMD,
 987                      NULL,
 988                      0, 
 989                      (unsigned char *) sony_toc, 
 990                      &res_size);
 991       if ((res_size < 2) || ((sony_toc->exec_status[0] & 0x20) == 0x20))
 992       {
 993          return;
 994       }
 995       sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
 996       sony_toc_read = 1;
 997    }
 998 }
 999 
1000 
1001 /*
1002  * Search for a specific track in the table of contents.
1003  */
1004 static int
1005 find_track(int track)
     /* [previous][next][first][last][top][bottom][index][help] */
1006 {
1007    int i;
1008    int num_tracks;
1009 
1010 
1011    num_tracks = sony_toc->last_track_num + sony_toc->first_track_num + 1;
1012    for (i = 0; i < num_tracks; i++)
1013    {
1014       if (sony_toc->tracks[i].track == track)
1015       {
1016          return i;
1017       }
1018    }
1019 
1020    return -1;
1021 }
1022 
1023 
1024 /*
1025  * Read the subcode and put it int last_sony_subcode for future use.
1026  */
1027 static int
1028 read_subcode(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1029 {
1030    unsigned int res_size;
1031 
1032 
1033    do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
1034                   NULL,
1035                   0, 
1036                   (unsigned char *) last_sony_subcode, 
1037                   &res_size);
1038    if ((res_size < 2) || ((last_sony_subcode->exec_status[0] & 0x20) == 0x20))
1039    {
1040       printk("Sony CDROM error 0x%2.2x (read_subcode)\n",
1041              last_sony_subcode->exec_status[1]);
1042       return -EIO;
1043    }
1044 
1045    return 0;
1046 }
1047 
1048 
1049 /*
1050  * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
1051  * the drive is playing, the subchannel needs to be read (since it would be
1052  * changing).  If the drive is paused or completed, the subcode information has
1053  * already been stored, just use that.  The ioctl call wants things in decimal
1054  * (not BCD), so all the conversions are done.
1055  */
1056 static int
1057 sony_get_subchnl_info(long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1058 {
1059    struct cdrom_subchnl schi;
1060 
1061 
1062    /* Get attention stuff */
1063    while (handle_sony_cd_attention())
1064       ;
1065 
1066    sony_get_toc();
1067    if (!sony_toc_read)
1068    {
1069       return -EIO;
1070    }
1071 
1072    verify_area(VERIFY_READ, (char *) arg, sizeof(schi));
1073    verify_area(VERIFY_WRITE, (char *) arg, sizeof(schi));
1074 
1075    memcpy_fromfs(&schi, (char *) arg, sizeof(schi));
1076    
1077    switch (sony_audio_status)
1078    {
1079    case CDROM_AUDIO_PLAY:
1080       if (read_subcode() < 0)
1081       {
1082          return -EIO;
1083       }
1084       break;
1085 
1086    case CDROM_AUDIO_PAUSED:
1087    case CDROM_AUDIO_COMPLETED:
1088       break;
1089 
1090    case CDROM_AUDIO_NO_STATUS:
1091       schi.cdsc_audiostatus = sony_audio_status;
1092       memcpy_tofs((char *) arg, &schi, sizeof(schi));
1093       return 0;
1094       break;
1095 
1096    case CDROM_AUDIO_INVALID:
1097    case CDROM_AUDIO_ERROR:
1098    default:
1099       return -EIO;
1100    }
1101 
1102    schi.cdsc_audiostatus = sony_audio_status;
1103    schi.cdsc_adr = last_sony_subcode->address;
1104    schi.cdsc_ctrl = last_sony_subcode->control;
1105    schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
1106    schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
1107    if (schi.cdsc_format == CDROM_MSF)
1108    {
1109       schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
1110       schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
1111       schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
1112 
1113       schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
1114       schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
1115       schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
1116    }
1117    else if (schi.cdsc_format == CDROM_LBA)
1118    {
1119       schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
1120       schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
1121    }
1122    
1123    memcpy_tofs((char *) arg, &schi, sizeof(schi));
1124    return 0;
1125 }
1126 
1127 
1128 /*
1129  * The big ugly ioctl handler.
1130  */
1131 static int
1132 scd_ioctl(struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
1133           struct file  *file,
1134           unsigned int cmd,
1135           unsigned int arg)
1136 {
1137    unsigned int dev;
1138    unsigned char res_reg[2];
1139    unsigned int res_size;
1140    unsigned char params[7];
1141    int i;
1142 
1143 
1144    if (!inode)
1145    {
1146       return -EINVAL;
1147    }
1148    dev = MINOR(inode->i_rdev) >> 6;
1149    if (dev != 0)
1150    {
1151       return -EINVAL;
1152    }
1153 
1154    switch (cmd)
1155    {
1156    case CDROMSTART:     /* Spin up the drive */
1157       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1158       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1159       {
1160          printk("Sony CDROM error 0x%2.2x (CDROMSTART)\n", res_reg[1]);
1161          return -EIO;
1162       }
1163       return 0;
1164       break;
1165       
1166    case CDROMSTOP:      /* Spin down the drive */
1167       do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1168 
1169       /*
1170        * Spin the drive down, ignoring the error if the disk was
1171        * already not spinning.
1172        */
1173       sony_audio_status = CDROM_AUDIO_NO_STATUS;
1174       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1175       if (   ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1176           && (res_reg[1] != SONY_NOT_SPIN_ERR))
1177       {
1178          printk("Sony CDROM error 0x%2.2x (CDROMSTOP)\n", res_reg[1]);
1179          return -EIO;
1180       }
1181       
1182       return 0;
1183       break;
1184 
1185    case CDROMPAUSE:     /* Pause the drive */
1186       do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1187       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1188       {
1189          printk("Sony CDROM error 0x%2.2x (CDROMPAUSE)\n", res_reg[1]);
1190          return -EIO;
1191       }
1192 
1193       /* Get the current position and save it for resuming */
1194       if (read_subcode() < 0)
1195       {
1196          return -EIO;
1197       }
1198       cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
1199       cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
1200       cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
1201       sony_audio_status = CDROM_AUDIO_PAUSED;
1202       return 0;
1203       break;
1204 
1205    case CDROMRESUME:    /* Start the drive after being paused */
1206       if (sony_audio_status != CDROM_AUDIO_PAUSED)
1207       {
1208          return -EINVAL;
1209       }
1210       
1211       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1212       
1213       /* Start the drive at the saved position. */
1214       params[1] = cur_pos_msf[0];
1215       params[2] = cur_pos_msf[1];
1216       params[3] = cur_pos_msf[2];
1217       params[4] = final_pos_msf[0];
1218       params[5] = final_pos_msf[1];
1219       params[6] = final_pos_msf[2];
1220       params[0] = 0x03;
1221       do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1222       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1223       {
1224          printk("Sony CDROM error 0x%2.2x (CDROMRESUME)\n", res_reg[1]);
1225          return -EIO;
1226       }
1227       sony_audio_status = CDROM_AUDIO_PLAY;
1228       return 0;
1229       break;
1230 
1231    case CDROMPLAYMSF:   /* Play starting at the given MSF address. */
1232       verify_area(VERIFY_READ, (char *) arg, 6);
1233       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1234       memcpy_fromfs(&(params[1]), (void *) arg, 6);
1235       
1236       /* The parameters are given in int, must be converted */
1237       for (i=1; i<7; i++)
1238       {
1239          params[i] = int_to_bcd(params[i]);
1240       }
1241       params[0] = 0x03;
1242       do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1243       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1244       {
1245          printk("Sony CDROM error 0x%2.2x (CDROMPLAYMSF)\n", res_reg[1]);
1246          return -EIO;
1247       }
1248       
1249       /* Save the final position for pauses and resumes */
1250       final_pos_msf[0] = params[4];
1251       final_pos_msf[1] = params[5];
1252       final_pos_msf[2] = params[6];
1253       sony_audio_status = CDROM_AUDIO_PLAY;
1254       return 0;
1255       break;
1256 
1257    case CDROMREADTOCHDR:        /* Read the table of contents header */
1258       {
1259          struct cdrom_tochdr *hdr;
1260          struct cdrom_tochdr loc_hdr;
1261          
1262          sony_get_toc();
1263          if (!sony_toc_read)
1264          {
1265             return -EIO;
1266          }
1267          
1268          hdr = (struct cdrom_tochdr *) arg;
1269          verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
1270          loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
1271          loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
1272          memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));
1273       }
1274       return 0;
1275       break;
1276 
1277    case CDROMREADTOCENTRY:      /* Read a given table of contents entry */
1278       {
1279          struct cdrom_tocentry *entry;
1280          struct cdrom_tocentry loc_entry;
1281          int track_idx;
1282          unsigned char *msf_val = NULL;
1283          
1284          sony_get_toc();
1285          if (!sony_toc_read)
1286          {
1287             return -EIO;
1288          }
1289          
1290          entry = (struct cdrom_tocentry *) arg;
1291          verify_area(VERIFY_READ, entry, sizeof(*entry));
1292          verify_area(VERIFY_WRITE, entry, sizeof(*entry));
1293          
1294          memcpy_fromfs(&loc_entry, entry, sizeof(loc_entry));
1295          
1296          /* Lead out is handled separately since it is special. */
1297          if (loc_entry.cdte_track == CDROM_LEADOUT)
1298          {
1299             loc_entry.cdte_adr = sony_toc->address2;
1300             loc_entry.cdte_ctrl = sony_toc->control2;
1301             msf_val = sony_toc->lead_out_start_msf;
1302          }
1303          else
1304          {
1305             track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
1306             if (track_idx < 0)
1307             {
1308                return -EINVAL;
1309             }
1310             
1311             loc_entry.cdte_adr = sony_toc->tracks[track_idx].address;
1312             loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
1313             msf_val = sony_toc->tracks[track_idx].track_start_msf;
1314          }
1315          
1316          /* Logical buffer address or MSF format requested? */
1317          if (loc_entry.cdte_format == CDROM_LBA)
1318          {
1319             loc_entry.cdte_addr.lba = msf_to_log(msf_val);
1320          }
1321          else if (loc_entry.cdte_format == CDROM_MSF)
1322          {
1323             loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
1324             loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val+1));
1325             loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val+2));
1326          }
1327          memcpy_tofs(entry, &loc_entry, sizeof(*entry));
1328       }
1329       return 0;
1330       break;
1331 
1332    case CDROMPLAYTRKIND:     /* Play a track.  This currently ignores index. */
1333       {
1334          struct cdrom_ti ti;
1335          int track_idx;
1336          
1337          sony_get_toc();
1338          if (!sony_toc_read)
1339          {
1340             return -EIO;
1341          }
1342          
1343          verify_area(VERIFY_READ, (char *) arg, sizeof(ti));
1344          
1345          memcpy_fromfs(&ti, (char *) arg, sizeof(ti));
1346          if (   (ti.cdti_trk0 < sony_toc->first_track_num)
1347              || (ti.cdti_trk0 > sony_toc->last_track_num)
1348              || (ti.cdti_trk1 < ti.cdti_trk0))
1349          {
1350             return -EINVAL;
1351          }
1352          
1353          track_idx = find_track(int_to_bcd(ti.cdti_trk0));
1354          if (track_idx < 0)
1355          {
1356             return -EINVAL;
1357          }
1358          params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
1359          params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
1360          params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
1361          
1362          /*
1363           * If we want to stop after the last track, use the lead-out
1364           * MSF to do that.
1365           */
1366          if (ti.cdti_trk1 >= bcd_to_int(sony_toc->last_track_num))
1367          {
1368             log_to_msf(msf_to_log(sony_toc->lead_out_start_msf)-1,
1369                        &(params[4]));
1370          }
1371          else
1372          {
1373             track_idx = find_track(int_to_bcd(ti.cdti_trk1+1));
1374             if (track_idx < 0)
1375             {
1376                return -EINVAL;
1377             }
1378             log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf)-1,
1379                        &(params[4]));
1380          }
1381          params[0] = 0x03;
1382          
1383          do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1384          
1385          do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1386          if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1387          {
1388             printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1],
1389                    params[2], params[3], params[4], params[5], params[6]);
1390             printk("Sony CDROM error 0x%2.2x (CDROMPLAYTRKIND\n", res_reg[1]);
1391             return -EIO;
1392          }
1393          
1394          /* Save the final position for pauses and resumes */
1395          final_pos_msf[0] = params[4];
1396          final_pos_msf[1] = params[5];
1397          final_pos_msf[2] = params[6];
1398          sony_audio_status = CDROM_AUDIO_PLAY;
1399          return 0;
1400       }
1401      
1402    case CDROMSUBCHNL:   /* Get subchannel info */
1403       return sony_get_subchnl_info(arg);
1404 
1405    case CDROMVOLCTRL:   /* Volume control.  What volume does this change, anyway? */
1406       {
1407          struct cdrom_volctrl volctrl;
1408          
1409          verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));
1410          
1411          memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
1412          params[0] = SONY_SD_AUDIO_VOLUME;
1413          params[1] = volctrl.channel0;
1414          params[2] = volctrl.channel1;
1415          do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);
1416          if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1417          {
1418             printk("Sony CDROM error 0x%2.2x (CDROMVOLCTRL)\n", res_reg[1]);
1419             return -EIO;
1420          }
1421       }
1422       return 0;
1423 
1424    case CDROMEJECT:     /* Eject the drive */
1425       do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1426       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1427 
1428       sony_audio_status = CDROM_AUDIO_INVALID;
1429       do_sony_cd_cmd(SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
1430       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1431       {
1432          printk("Sony CDROM error 0x%2.2x (CDROMEJECT)\n", res_reg[1]);
1433          return -EIO;
1434       }
1435       return 0;
1436       break;
1437      
1438    default:
1439       return -EINVAL;
1440    }
1441 }
1442 
1443 
1444 /*
1445  * Open the drive for operations.  Spin the drive up and read the table of
1446  * contents if these have not already been done.
1447  */
1448 static int
1449 scd_open(struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
1450          struct file *filp)
1451 {
1452    unsigned char res_reg[2];
1453    unsigned int res_size;
1454 
1455 
1456    if (!sony_spun_up)
1457    {
1458       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1459 
1460       /* The drive sometimes returns error 0.  I don't know why, but ignore
1461          it.  It seems to mean the drive has already done the operation. */
1462       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
1463       {
1464          printk("Sony CDROM error 0x%2.2x (scd_open, spin up)\n", res_reg[1]);
1465          return -EIO;
1466       }
1467       
1468       do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
1469 
1470       /* The drive sometimes returns error 0.  I don't know why, but ignore
1471          it.  It seems to mean the drive has already done the operation. */
1472       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
1473       {
1474          /* If the drive is already playing, its ok.  */
1475          if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))
1476          {
1477             goto drive_spinning;
1478          }
1479 
1480          printk("Sony CDROM error 0x%2.2x (scd_open, read toc)\n", res_reg[1]);
1481          do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1482          
1483          return -EIO;
1484       }
1485 
1486       sony_get_toc();
1487       if (!sony_toc_read)
1488       {
1489          do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1490          return -EIO;
1491       }
1492 
1493       sony_spun_up = 1;
1494    }
1495 
1496 drive_spinning:
1497 
1498    if (inode)
1499    {
1500       check_disk_change(inode->i_rdev);
1501    }
1502 
1503    sony_usage++;
1504 
1505    return 0;
1506 }
1507 
1508 
1509 /*
1510  * Close the drive.  Spin it down if no task is using it.  The spin
1511  * down will fail if playing audio, so audio play is OK.
1512  */
1513 static void
1514 scd_release(struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
1515          struct file *filp)
1516 {
1517    unsigned char res_reg[2];
1518    unsigned int  res_size;
1519 
1520 
1521    if (sony_usage > 0)
1522    {
1523       sony_usage--;
1524    }
1525    if (sony_usage == 0)
1526    {
1527       sync_dev(inode->i_rdev);
1528       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1529 
1530       sony_spun_up = 0;
1531    }
1532 }
1533 
1534 
1535 static struct file_operations scd_fops = {
1536    NULL,                   /* lseek - default */
1537    block_read,             /* read - general block-dev read */
1538    block_write,            /* write - general block-dev write */
1539    NULL,                   /* readdir - bad */
1540    NULL,                   /* select */
1541    scd_ioctl,              /* ioctl */
1542    NULL,                   /* mmap */
1543    scd_open,               /* open */
1544    scd_release             /* release */
1545 };
1546 
1547 
1548 /* The different types of disc loading mechanisms supported */
1549 static char *load_mech[] = { "caddy", "tray", "pop-up", "unknown" };
1550 
1551 /* Read-ahead buffer sizes for different drives.  These are just arbitrary
1552    values, I don't know what is really optimum. */
1553 static unsigned int mem_size[] = { 4096, 8192, 16384, 2048 };
1554 
1555 void
1556 get_drive_configuration(unsigned short base_io,
     /* [previous][next][first][last][top][bottom][index][help] */
1557                         unsigned char res_reg[],
1558                         unsigned int *res_size)
1559 {
1560    int retry_count;
1561 
1562 
1563    /* Set the base address */
1564    sony_cd_base_io = base_io;
1565 
1566    /* Set up all the register locations */
1567    sony_cd_cmd_reg = sony_cd_base_io + SONY_CMD_REG_OFFSET;
1568    sony_cd_param_reg = sony_cd_base_io + SONY_PARAM_REG_OFFSET;
1569    sony_cd_write_reg = sony_cd_base_io + SONY_WRITE_REG_OFFSET;
1570    sony_cd_control_reg = sony_cd_base_io + SONY_CONTROL_REG_OFFSET;
1571    sony_cd_status_reg = sony_cd_base_io + SONY_STATUS_REG_OFFSET;
1572    sony_cd_result_reg = sony_cd_base_io + SONY_RESULT_REG_OFFSET;
1573    sony_cd_read_reg = sony_cd_base_io + SONY_READ_REG_OFFSET;
1574    sony_cd_fifost_reg = sony_cd_base_io + SONY_FIFOST_REG_OFFSET;
1575 
1576    /*
1577     * Check to see if anything exists at the status register location.
1578     * I don't know if this is a good way to check, but it seems to work
1579     * ok for me.
1580     */
1581    if (read_status_register() != 0xff)
1582    {
1583       /*
1584        * Reset the drive and wait for attention from it (to say its reset).
1585        * If you don't wait, the next operation will probably fail.
1586        */
1587       reset_drive();
1588       retry_count = jiffies + SONY_RESET_TIMEOUT;
1589       while ((retry_count > jiffies) && (!is_attention()))
1590       {
1591          sony_sleep();
1592       }
1593 
1594       /* If attention is never seen probably not a CDU31a present */
1595       if (!is_attention())
1596       {
1597          res_reg[0] = 0x20;
1598          return;
1599       }
1600 
1601       /*
1602        * Get the drive configuration.
1603        */
1604       do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
1605                      NULL,
1606                      0,
1607                      (unsigned char *) res_reg,
1608                      res_size);
1609       return;
1610    }
1611 
1612    /* Return an error */
1613    res_reg[0] = 0x20;
1614 }
1615 
1616 
1617 /*
1618  * Initialize the driver.
1619  */
1620 unsigned long
1621 cdu31a_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
1622 {
1623    struct s_sony_drive_config drive_config;
1624    unsigned char params[3];
1625    unsigned char res_reg[2];
1626    unsigned int res_size;
1627    int i;
1628    int drive_found;
1629 
1630 
1631    /*
1632     * According to Alex Freed (freed@europa.orion.adobe.com), this is
1633     * required for the Fusion CD-16 package.  If the sound driver is
1634     * loaded, it should work fine, but just in case...
1635     *
1636     * The following turn on the CD-ROM interface for a Fusion CD-16.
1637     */
1638    outb(0xbc, 0x9a01);
1639    outb(0xe2, 0x9a01);
1640 
1641    i = 0;
1642    drive_found = 0;
1643    while (   (cdu31a_addresses[i] != 0)
1644           && (!drive_found))
1645    {
1646       get_drive_configuration(cdu31a_addresses[i],
1647                                drive_config.exec_status,
1648                                &res_size);
1649       if ((res_size > 2) && ((drive_config.exec_status[0] & 0x20) == 0x00))
1650       {
1651          drive_found = 1;
1652 
1653          if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops))
1654          {
1655             printk("Unable to get major %d for CDU-31a\n", MAJOR_NR);
1656             return mem_start;
1657          }
1658 
1659          sony_buffer_size = mem_size[SONY_HWC_GET_BUF_MEM_SIZE(drive_config)];
1660          sony_buffer_sectors = sony_buffer_size / 2048;
1661 
1662          printk("Sony I/F CDROM : %8.8s %16.16s %8.8s with %s load mechanism\n",
1663                 drive_config.vendor_id,
1664                 drive_config.product_id,
1665                 drive_config.product_rev_level,
1666                 load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
1667          printk("  using %d byte buffer", sony_buffer_size);
1668          if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
1669          {
1670             printk(", capable of audio playback");
1671          }
1672          printk("\n");
1673 
1674          params[0] = SONY_SD_MECH_CONTROL;
1675          params[1] = 0x03;
1676          do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
1677                         params,
1678                         2,
1679                         res_reg,
1680                         &res_size);
1681          if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1682          {
1683             printk("  Unable to set mechanical parameters: 0x%2.2x\n", res_reg[1]);
1684          }
1685 
1686          blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1687          read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
1688 
1689          sony_toc = (struct s_sony_toc *) mem_start;
1690          mem_start += sizeof(*sony_toc);
1691          last_sony_subcode = (struct s_sony_subcode *) mem_start;
1692          mem_start += sizeof(*last_sony_subcode);
1693          sony_buffer = (unsigned char *) mem_start;
1694          mem_start += sony_buffer_size;
1695 
1696          initialized = 1;
1697       }
1698 
1699       i++;
1700    }
1701    
1702    return mem_start;
1703 }
1704 
1705 #endif

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