root/drivers/cdrom/sjcd.c

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

DEFINITIONS

This source file includes following definitions.
  1. sjcd_setup
  2. bin2bcd
  3. bcd2bin
  4. msf2hsg
  5. hsg2msf
  6. sjcd_send_cmd
  7. sjcd_send_1_cmd
  8. sjcd_send_4_cmd
  9. sjcd_send_6_cmd
  10. sjcd_load_response
  11. sjcd_load_status
  12. sjcd_check_status
  13. sjcd_status_timer
  14. sjcd_wait_for_status
  15. sjcd_receive_status
  16. sjcd_get_status
  17. sjcd_disk_change
  18. sjcd_update_toc
  19. sjcd_get_q_info
  20. sjcd_play
  21. sjcd_tray_close
  22. sjcd_tray_lock
  23. sjcd_tray_unlock
  24. sjcd_tray_open
  25. sjcd_ioctl
  26. sjcd_invalidate_buffers
  27. sjcd_transfer
  28. sjcd_poll
  29. do_sjcd_request
  30. sjcd_open
  31. sjcd_release
  32. sjcd_init
  33. cleanup_module
  34. isp16_detect
  35. isp16_c928__detect
  36. isp16_c929__detect
  37. isp16_cdi_config
  38. isp16_sound_config

   1 /* -- sjcd.c
   2  *
   3  *   Sanyo CD-ROM device driver implementation, Version 1.5
   4  *   Copyright (C) 1995  Vadim V. Model
   5  *
   6  *   model@cecmow.enet.dec.com
   7  *   vadim@rbrf.ru
   8  *   vadim@ipsun.ras.ru
   9  *
  10  *   ISP16 detection and configuration.
  11  *   Copyright (C) 1995  Eric van der Maarel (maarel@marin.nl)
  12  *                   and Vadim Model (vadim@cecmow.enet.dec.com)
  13  *
  14  *
  15  *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
  16  *  it was developed under use of mcd.c from Martin Harriss, with help of
  17  *  Eric van der Maarel (maarel@marin.nl).
  18  *
  19  *  ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl).
  20  *  Sound configuration by Vadim V. Model (model@cecmow.enet.dec.com)
  21  *
  22  *  It is planned to include these routines into sbpcd.c later - to make
  23  *  a "mixed use" on one cable possible for all kinds of drives which use
  24  *  the SoundBlaster/Panasonic style CDROM interface. But today, the
  25  *  ability to install directly from CDROM is more important than flexibility.
  26  *
  27  *  This program is free software; you can redistribute it and/or modify
  28  *  it under the terms of the GNU General Public License as published by
  29  *  the Free Software Foundation; either version 2 of the License, or
  30  *  (at your option) any later version.
  31  *
  32  *  This program is distributed in the hope that it will be useful,
  33  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  34  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35  *  GNU General Public License for more details.
  36  *
  37  *  You should have received a copy of the GNU General Public License
  38  *  along with this program; if not, write to the Free Software
  39  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40  *
  41  *  History:
  42  *  1.1 First public release with kernel version 1.3.7.
  43  *      Written by Vadim Model.
  44  *  1.2 Added detection and configuration of cdrom interface
  45  *      on ISP16 soundcard.
  46  *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
  47  *  1.3 Some minor changes to README.sjcd.
  48  *  1.4 MSS Sound support!! Listen to a CD through the speakers.
  49  *  1.5 Module support and bugfixes.
  50  *      Tray locking.
  51  *
  52  */
  53 
  54 #include <linux/major.h>
  55 #include <linux/config.h>
  56 
  57 #ifdef MODULE
  58 #include <linux/module.h>
  59 #include <linux/version.h>
  60 #define sjcd_init init_module
  61 #ifndef CONFIG_MODVERSIONS
  62 char kernel_version[]= UTS_RELEASE;
  63 #endif
  64 #endif
  65 
  66 #include <linux/errno.h>
  67 #include <linux/sched.h>
  68 #include <linux/mm.h>
  69 #include <linux/timer.h>
  70 #include <linux/fs.h>
  71 #include <linux/kernel.h>
  72 #include <linux/cdrom.h>
  73 #include <linux/ioport.h>
  74 #include <linux/string.h>
  75 
  76 #include <asm/system.h>
  77 #include <asm/io.h>
  78 #include <asm/segment.h>
  79 
  80 #define MAJOR_NR SANYO_CDROM_MAJOR
  81 #include <linux/blk.h>
  82 #include <linux/sjcd.h>
  83 
  84 /* Some (Media)Magic */
  85 /* define types of drive the interface on an ISP16 card may be looking at */
  86 #define ISP16_DRIVE_X 0x00
  87 #define ISP16_SONY  0x02
  88 #define ISP16_PANASONIC0 0x02
  89 #define ISP16_SANYO0 0x02
  90 #define ISP16_MITSUMI  0x04
  91 #define ISP16_PANASONIC1 0x06
  92 #define ISP16_SANYO1 0x06
  93 #define ISP16_DRIVE_NOT_USED 0x08  /* not used */
  94 #define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
  95 /* ...for port */
  96 #define ISP16_DRIVE_SET_PORT 0xF8D
  97 /* set io parameters */
  98 #define ISP16_BASE_340  0x00
  99 #define ISP16_BASE_330  0x40
 100 #define ISP16_BASE_360  0x80
 101 #define ISP16_BASE_320  0xC0
 102 #define ISP16_IRQ_X  0x00
 103 #define ISP16_IRQ_5  0x04  /* shouldn't be used due to soundcard conflicts */
 104 #define ISP16_IRQ_7  0x08  /* shouldn't be used due to soundcard conflicts */
 105 #define ISP16_IRQ_3  0x0C
 106 #define ISP16_IRQ_9  0x10
 107 #define ISP16_IRQ_10  0x14
 108 #define ISP16_IRQ_11  0x18
 109 #define ISP16_DMA_X  0x03
 110 #define ISP16_DMA_3  0x00
 111 #define ISP16_DMA_5  0x00
 112 #define ISP16_DMA_6  0x01
 113 #define ISP16_DMA_7  0x02
 114 #define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
 115 /* ...for port */
 116 #define ISP16_IO_SET_PORT  0xF8E
 117 /* enable the card */
 118 #define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
 119 #define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
 120 #define ISP16_ENABLE_CDROM  0x80  /* seven bit */
 121 
 122 /* the magic stuff */
 123 #define ISP16_CTRL_PORT  0xF8F
 124 #define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
 125 #define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
 126 
 127 static short isp16_detect(void);
 128 static short isp16_c928__detect(void);
 129 static short isp16_c929__detect(void);
 130 static short isp16_cdi_config( int base, u_char drive_type, int irq, int dma );
 131 static void isp16_sound_config( void );
 132 static short isp16_type; /* dependent on type of interface card */
 133 static u_char isp16_ctrl;
 134 static u_short isp16_enable_port;
 135 
 136 static int sjcd_present = 0;
 137 static u_char special_mask = 0;
 138 
 139 static unsigned char defaults[ 16 ] = {
 140   0xA8, 0xA8, 0x18, 0x18, 0x18, 0x18, 0x8E, 0x8E,
 141   0x03, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00
 142 };
 143 
 144 #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
 145 
 146 /*
 147  * buffer for block size conversion
 148  */
 149 static char sjcd_buf[ 2048 * SJCD_BUF_SIZ ];
 150 static volatile int sjcd_buf_bn[ SJCD_BUF_SIZ ], sjcd_next_bn;
 151 static volatile int sjcd_buf_in, sjcd_buf_out = -1;
 152 
 153 /*
 154  * Status.
 155  */
 156 static unsigned short sjcd_status_valid = 0;
 157 static unsigned short sjcd_door_closed;
 158 static unsigned short sjcd_door_was_open;
 159 static unsigned short sjcd_media_is_available;
 160 static unsigned short sjcd_media_is_changed;
 161 static unsigned short sjcd_toc_uptodate = 0;
 162 static unsigned short sjcd_command_failed;
 163 static volatile unsigned char sjcd_completion_status = 0;
 164 static volatile unsigned char sjcd_completion_error = 0;
 165 static unsigned short sjcd_command_is_in_progress = 0;
 166 static unsigned short sjcd_error_reported = 0;
 167 
 168 static int sjcd_open_count;
 169 
 170 static int sjcd_audio_status;
 171 static struct sjcd_play_msf sjcd_playing;
 172 
 173 static int sjcd_port = SJCD_BASE_ADDR;
 174 static int sjcd_irq  = SJCD_INTR_NR;
 175 static int sjcd_dma  = SJCD_DMA_NR;
 176 
 177 static struct wait_queue *sjcd_waitq = NULL;
 178 
 179 /*
 180  * Data transfer.
 181  */
 182 static volatile unsigned short sjcd_transfer_is_active = 0;
 183 
 184 enum sjcd_transfer_state {
 185   SJCD_S_IDLE     = 0,
 186   SJCD_S_START    = 1,
 187   SJCD_S_MODE     = 2,
 188   SJCD_S_READ     = 3,
 189   SJCD_S_DATA     = 4,
 190   SJCD_S_STOP     = 5,
 191   SJCD_S_STOPPING = 6
 192 };
 193 static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
 194 static long sjcd_transfer_timeout = 0;
 195 static int sjcd_read_count = 0;
 196 static unsigned char sjcd_mode = 0;
 197 
 198 #define SJCD_READ_TIMEOUT 5000
 199 
 200 #if defined( SJCD_GATHER_STAT )
 201 /*
 202  * Statistic.
 203  */
 204 static struct sjcd_stat statistic;
 205 #endif
 206 
 207 /*
 208  * Timer.
 209  */
 210 static struct timer_list sjcd_delay_timer = { NULL, NULL, 0, 0, NULL };
 211 
 212 #define SJCD_SET_TIMER( func, tmout )           \
 213     ( sjcd_delay_timer.expires = jiffies+tmout,         \
 214       sjcd_delay_timer.function = ( void * )func, \
 215       add_timer( &sjcd_delay_timer ) )
 216 
 217 #define CLEAR_TIMER del_timer( &sjcd_delay_timer )
 218 
 219 /*
 220  * Set up device, i.e., use command line data to set
 221  * base address, irq and dma.
 222  */
 223 void sjcd_setup( char *str, int *ints )
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225    if (ints[0] > 0)
 226       sjcd_port = ints[1];
 227    if (ints[0] > 1)      
 228       sjcd_irq = ints[2];
 229    if (ints[0] > 2)      
 230       sjcd_dma = ints[3];
 231 }
 232 
 233 /*
 234  * Special converters.
 235  */
 236 static unsigned char bin2bcd( int bin ){
     /* [previous][next][first][last][top][bottom][index][help] */
 237   int u, v;
 238 
 239   u = bin % 10; v = bin / 10;
 240   return( u | ( v << 4 ) );
 241 }
 242 
 243 static int bcd2bin( unsigned char bcd ){
     /* [previous][next][first][last][top][bottom][index][help] */
 244     return( ( bcd >> 4 ) * 10 + ( bcd & 0x0F ) );
 245 }
 246 
 247 static long msf2hsg( struct msf *mp ){
     /* [previous][next][first][last][top][bottom][index][help] */
 248   return( bcd2bin( mp->frame ) + bcd2bin( mp->sec ) * 75
 249          + bcd2bin( mp->min ) * 4500 - 150 );
 250 }
 251 
 252 static void hsg2msf( long hsg, struct msf *msf ){
     /* [previous][next][first][last][top][bottom][index][help] */
 253   hsg += 150; msf->min = hsg / 4500;
 254   hsg %= 4500; msf->sec = hsg / 75; msf->frame = hsg % 75;
 255   msf->min = bin2bcd( msf->min );       /* convert to BCD */
 256   msf->sec = bin2bcd( msf->sec );
 257   msf->frame = bin2bcd( msf->frame );
 258 }
 259 
 260 /*
 261  * Send a command to cdrom. Invalidate status.
 262  */
 263 static void sjcd_send_cmd( unsigned char cmd ){
     /* [previous][next][first][last][top][bottom][index][help] */
 264 #if defined( SJCD_TRACE )
 265   printk( "sjcd: send_cmd( 0x%x )\n", cmd );
 266 #endif
 267   outb( cmd, SJCDPORT( 0 ) );
 268   sjcd_command_is_in_progress = 1;
 269   sjcd_status_valid = 0;
 270   sjcd_command_failed = 0;
 271 }
 272 
 273 /*
 274  * Send a command with one arg to cdrom. Invalidate status.
 275  */
 276 static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){
     /* [previous][next][first][last][top][bottom][index][help] */
 277 #if defined( SJCD_TRACE )
 278   printk( "sjcd: send_1_cmd( 0x%x, 0x%x )\n", cmd, a );
 279 #endif
 280   outb( cmd, SJCDPORT( 0 ) );
 281   outb( a, SJCDPORT( 0 ) );
 282   sjcd_command_is_in_progress = 1;
 283   sjcd_status_valid = 0;
 284   sjcd_command_failed = 0;
 285 }
 286 
 287 /*
 288  * Send a command with four args to cdrom. Invalidate status.
 289  */
 290 static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a,
     /* [previous][next][first][last][top][bottom][index][help] */
 291             unsigned char b, unsigned char c, unsigned char d ){
 292 #if defined( SJCD_TRACE )
 293   printk( "sjcd: send_4_cmd( 0x%x )\n", cmd );
 294 #endif
 295   outb( cmd, SJCDPORT( 0 ) );
 296   outb( a, SJCDPORT( 0 ) );
 297   outb( b, SJCDPORT( 0 ) );
 298   outb( c, SJCDPORT( 0 ) );
 299   outb( d, SJCDPORT( 0 ) );
 300   sjcd_command_is_in_progress = 1;
 301   sjcd_status_valid = 0;
 302   sjcd_command_failed = 0;
 303 }
 304 
 305 /*
 306  * Send a play or read command to cdrom. Invalidate Status.
 307  */
 308 static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){
     /* [previous][next][first][last][top][bottom][index][help] */
 309 #if defined( SJCD_TRACE )
 310   printk( "sjcd: send_long_cmd( 0x%x )\n", cmd );
 311 #endif
 312   outb( cmd, SJCDPORT( 0 ) );
 313   outb( pms->start.min,   SJCDPORT( 0 ) );
 314   outb( pms->start.sec,   SJCDPORT( 0 ) );
 315   outb( pms->start.frame, SJCDPORT( 0 ) );
 316   outb( pms->end.min,     SJCDPORT( 0 ) );
 317   outb( pms->end.sec,     SJCDPORT( 0 ) );
 318   outb( pms->end.frame,   SJCDPORT( 0 ) );
 319   sjcd_command_is_in_progress = 1;
 320   sjcd_status_valid = 0;
 321   sjcd_command_failed = 0;
 322 }
 323 
 324 /*
 325  * Get a value from the data port. Should not block, so we use a little
 326  * wait for a while. Returns 0 if OK.
 327  */
 328 static int sjcd_load_response( void *buf, int len ){
     /* [previous][next][first][last][top][bottom][index][help] */
 329   unsigned char *resp = ( unsigned char * )buf;
 330 
 331   for( ; len; --len ){ 
 332     int i;
 333     for( i = 200; i-- && !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ); );
 334     if( i > 0 ) *resp++ = ( unsigned char )inb( SJCDPORT( 0 ) );
 335     else break;
 336   }
 337   return( len );
 338 }
 339 
 340 /*
 341  * Load and parse command completion status (drive info byte and maybe error).
 342  * Sorry, no error classification yet.
 343  */
 344 static void sjcd_load_status( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 345   sjcd_media_is_changed = 0;
 346   sjcd_completion_error = 0;
 347   sjcd_completion_status = inb( SJCDPORT( 0 ) );
 348   if( sjcd_completion_status & SST_DOOR_OPENED ){
 349     sjcd_door_closed = sjcd_media_is_available = 0;
 350   } else {
 351     sjcd_door_closed = 1;
 352     if( sjcd_completion_status & SST_MEDIA_CHANGED )
 353       sjcd_media_is_available = sjcd_media_is_changed = 1;
 354     else if( sjcd_completion_status & 0x0F ){
 355       /*
 356        * OK, we seem to catch an error ...
 357        */
 358       while( !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) );
 359       sjcd_completion_error = inb( SJCDPORT( 0 ) );
 360       if( ( sjcd_completion_status & 0x08 ) &&
 361          ( sjcd_completion_error & 0x40 ) )
 362         sjcd_media_is_available = 0;
 363       else sjcd_command_failed = 1;
 364     } else sjcd_media_is_available = 1;
 365   }
 366   /*
 367    * Ok, status loaded successfully.
 368    */
 369   sjcd_status_valid = 1, sjcd_error_reported = 0;
 370   sjcd_command_is_in_progress = 0;
 371 
 372   /*
 373    * If the disk is changed, the TOC is not valid.
 374    */
 375   if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0;
 376 #if defined( SJCD_TRACE )
 377   printk( "sjcd: status %02x.%02x loaded.\n",
 378          ( int )sjcd_completion_status, ( int )sjcd_completion_error );
 379 #endif
 380 }
 381 
 382 /*
 383  * Read status from cdrom. Check to see if the status is available.
 384  */
 385 static int sjcd_check_status( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 386   /*
 387    * Try to load the response from cdrom into buffer.
 388    */
 389   if( SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ){
 390     sjcd_load_status();
 391     return( 1 );
 392   } else {
 393     /*
 394      * No status is available.
 395      */
 396     return( 0 );
 397   }
 398 }
 399 
 400 /*
 401  * This is just timout counter, and nothing more. Surprized ? :-)
 402  */
 403 static volatile long sjcd_status_timeout;
 404 
 405 /*
 406  * We need about 10 seconds to wait. The longest command takes about 5 seconds
 407  * to probe the disk (usually after tray closed or drive reset). Other values
 408  * should be thought of for other commands.
 409  */
 410 #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
 411 
 412 static void sjcd_status_timer( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 413   if( sjcd_check_status() ){
 414     /*
 415      * The command completed and status is loaded, stop waiting.
 416      */
 417     wake_up( &sjcd_waitq );
 418   } else if( --sjcd_status_timeout <= 0 ){
 419     /*
 420      * We are timed out. 
 421      */
 422     wake_up( &sjcd_waitq );
 423   } else {
 424     /*
 425      * We have still some time to wait. Try again.
 426      */
 427     SJCD_SET_TIMER( sjcd_status_timer, 1 );
 428   }
 429 }
 430 
 431 /*
 432  * Wait for status for 10 sec approx. Returns non-positive when timed out.
 433  * Should not be used while reading data CDs.
 434  */
 435 static int sjcd_wait_for_status( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 436   sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
 437   SJCD_SET_TIMER( sjcd_status_timer, 1 ); 
 438   sleep_on( &sjcd_waitq );    
 439 #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
 440   if( sjcd_status_timeout <= 0 )
 441     printk( "sjcd: Error Wait For Status.\n" );
 442 #endif
 443   return( sjcd_status_timeout );
 444 }
 445 
 446 static int sjcd_receive_status( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 447   int i;
 448 #if defined( SJCD_TRACE )
 449   printk( "sjcd: receive_status\n" );
 450 #endif
 451   /*
 452    * Wait a bit for status available.
 453    */
 454   for( i = 200; i-- && ( sjcd_check_status() == 0 ); );
 455   if( i < 0 ){
 456 #if defined( SJCD_TRACE )
 457     printk( "sjcd: long wait for status\n" );
 458 #endif
 459     if( sjcd_wait_for_status() <= 0 )
 460       printk( "sjcd: Timeout when read status.\n" );
 461     else i = 0;
 462   }
 463   return( i );
 464 }
 465 
 466 /*
 467  * Load the status. Issue get status command and wait for status available.
 468  */
 469 static void sjcd_get_status( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 470 #if defined( SJCD_TRACE )
 471   printk( "sjcd: get_status\n" );
 472 #endif
 473   sjcd_send_cmd( SCMD_GET_STATUS );
 474   sjcd_receive_status();
 475 }
 476 
 477 /*
 478  * Check the drive if the disk is changed. Should be revised.
 479  */
 480 static int sjcd_disk_change( kdev_t full_dev ){
     /* [previous][next][first][last][top][bottom][index][help] */
 481 #if 0
 482   printk( "sjcd_disk_change( 0x%x )\n", full_dev );
 483 #endif
 484   if( MINOR( full_dev ) > 0 ){
 485     printk( "sjcd: request error: invalid device minor.\n" );
 486     return 0;
 487   }
 488   if( !sjcd_command_is_in_progress )
 489     sjcd_get_status();
 490   return( sjcd_status_valid ? sjcd_media_is_changed : 0 );
 491 }
 492 
 493 /*
 494  * Read the table of contents (TOC) and TOC header if necessary.
 495  * We assume that the drive contains no more than 99 toc entries.
 496  */
 497 static struct sjcd_hw_disk_info sjcd_table_of_contents[ SJCD_MAX_TRACKS ];
 498 static unsigned char sjcd_first_track_no, sjcd_last_track_no;
 499 #define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
 500 
 501 static int sjcd_update_toc( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 502   struct sjcd_hw_disk_info info;
 503   int i;
 504 #if defined( SJCD_TRACE )
 505   printk( "sjcd: update toc:\n" );
 506 #endif
 507   /*
 508    * check to see if we need to do anything
 509    */
 510   if( sjcd_toc_uptodate ) return( 0 );
 511 
 512   /*
 513    * Get the TOC start information.
 514    */
 515   sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK );
 516   sjcd_receive_status();
 517 
 518   if( !sjcd_status_valid ){
 519     printk( "cannot load status.\n" );
 520     return( -1 );
 521   }
 522 
 523   if( !sjcd_media_is_available ){
 524     printk( "no disk in drive\n" );
 525     return( -1 );
 526   }
 527 
 528   if( !sjcd_command_failed ){
 529     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
 530       printk( "cannot load response about TOC start.\n" );
 531       return( -1 );
 532     }
 533     sjcd_first_track_no = bcd2bin( info.un.track_no );
 534   } else {
 535     printk( "get first failed\n" );
 536     return( -1 );
 537   }
 538 #if defined( SJCD_TRACE )
 539   printk( "TOC start 0x%02x ", sjcd_first_track_no );
 540 #endif
 541   /*
 542    * Get the TOC finish information.
 543    */
 544   sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK );
 545   sjcd_receive_status();
 546 
 547   if( !sjcd_status_valid ){
 548     printk( "cannot load status.\n" );
 549     return( -1 );
 550   }
 551 
 552   if( !sjcd_media_is_available ){
 553     printk( "no disk in drive\n" );
 554     return( -1 );
 555   }
 556 
 557   if( !sjcd_command_failed ){
 558     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
 559       printk( "cannot load response about TOC finish.\n" );
 560       return( -1 );
 561     }
 562     sjcd_last_track_no = bcd2bin( info.un.track_no );
 563   } else {
 564     printk( "get last failed\n" );
 565     return( -1 );
 566   }
 567 #if defined( SJCD_TRACE )
 568   printk( "TOC finish 0x%02x ", sjcd_last_track_no );
 569 #endif
 570   for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){
 571     /*
 572      * Get the first track information.
 573      */
 574     sjcd_send_1_cmd( SCMD_GET_DISK_INFO, bin2bcd( i ) );
 575     sjcd_receive_status();
 576 
 577     if( !sjcd_status_valid ){
 578       printk( "cannot load status.\n" );
 579       return( -1 );
 580     }
 581 
 582     if( !sjcd_media_is_available ){
 583       printk( "no disk in drive\n" );
 584       return( -1 );
 585     }
 586 
 587     if( !sjcd_command_failed ){
 588       if( sjcd_load_response( &sjcd_table_of_contents[ i ],
 589                              sizeof( struct sjcd_hw_disk_info ) ) != 0 ){
 590         printk( "cannot load info for %d track\n", i );
 591         return( -1 );
 592       }
 593     } else {
 594       printk( "get info %d failed\n", i );
 595       return( -1 );
 596     }
 597   }
 598 
 599   /*
 600    * Get the disk lenght info.
 601    */
 602   sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE );
 603   sjcd_receive_status();
 604 
 605   if( !sjcd_status_valid ){
 606     printk( "cannot load status.\n" );
 607     return( -1 );
 608   }
 609 
 610   if( !sjcd_media_is_available ){
 611     printk( "no disk in drive\n" );
 612     return( -1 );
 613   }
 614 
 615   if( !sjcd_command_failed ){
 616     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
 617       printk( "cannot load response about disk size.\n" );
 618       return( -1 );
 619     }
 620     sjcd_disk_length.min = info.un.track_msf.min;
 621     sjcd_disk_length.sec = info.un.track_msf.sec;
 622     sjcd_disk_length.frame = info.un.track_msf.frame;
 623   } else {
 624     printk( "get size failed\n" );
 625     return( 1 );
 626   }
 627 #if defined( SJCD_TRACE )
 628   printk( "(%02x:%02x.%02x)\n", sjcd_disk_length.min,
 629          sjcd_disk_length.sec, sjcd_disk_length.frame );
 630 #endif
 631   return( 0 );
 632 }
 633 
 634 /*
 635  * Load subchannel information.
 636  */
 637 static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){
     /* [previous][next][first][last][top][bottom][index][help] */
 638   int s;
 639 #if defined( SJCD_TRACE )
 640   printk( "sjcd: load sub q\n" );
 641 #endif
 642   sjcd_send_cmd( SCMD_GET_QINFO );
 643   s = sjcd_receive_status();
 644   if( s < 0 || sjcd_command_failed || !sjcd_status_valid ){
 645     sjcd_send_cmd( 0xF2 );
 646     s = sjcd_receive_status();
 647     if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 );
 648     sjcd_send_cmd( SCMD_GET_QINFO );
 649     s = sjcd_receive_status();
 650     if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 );
 651   }
 652   if( sjcd_media_is_available )
 653     if( sjcd_load_response( qp, sizeof( *qp ) ) == 0 ) return( 0 );
 654   return( -1 );
 655 }
 656 
 657 /*
 658  * Start playing from the specified position.
 659  */
 660 static int sjcd_play( struct sjcd_play_msf *mp ){
     /* [previous][next][first][last][top][bottom][index][help] */
 661   struct sjcd_play_msf msf;
 662 
 663   /*
 664    * Turn the device to play mode.
 665    */
 666   sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_PLAY );
 667   if( sjcd_receive_status() < 0 ) return( -1 );
 668 
 669   /*
 670    * Seek to the starting point.
 671    */
 672   msf.start = mp->start;
 673   msf.end.min = msf.end.sec = msf.end.frame = 0x00;
 674   sjcd_send_6_cmd( SCMD_SEEK, &msf );
 675   if( sjcd_receive_status() < 0 ) return( -1 );
 676 
 677   /*
 678    * Start playing.
 679    */
 680   sjcd_send_6_cmd( SCMD_PLAY, mp );
 681   return( sjcd_receive_status() );
 682 }
 683 
 684 /*
 685  * Tray control functions.
 686  */
 687 static int sjcd_tray_close( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 688 #if defined( SJCD_TRACE )
 689   printk( "sjcd: tray_close\n" );
 690 #endif
 691   sjcd_send_cmd( SCMD_CLOSE_TRAY );
 692   return( sjcd_receive_status() );
 693 }
 694 
 695 static int sjcd_tray_lock( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 696 #if defined( SJCD_TRACE )
 697   printk( "sjcd: tray_lock\n" );
 698 #endif
 699   sjcd_send_cmd( SCMD_LOCK_TRAY );
 700   return( sjcd_receive_status() );
 701 }
 702 
 703 static int sjcd_tray_unlock( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 704 #if defined( SJCD_TRACE )
 705   printk( "sjcd: tray_unlock\n" );
 706 #endif
 707   sjcd_send_cmd( SCMD_UNLOCK_TRAY );
 708   return( sjcd_receive_status() );
 709 }
 710 
 711 static int sjcd_tray_open( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 712 #if defined( SJCD_TRACE )
 713   printk( "sjcd: tray_open\n" );
 714 #endif
 715   sjcd_send_cmd( SCMD_EJECT_TRAY );
 716   return( sjcd_receive_status() );
 717 }
 718 
 719 /*
 720  * Do some user commands.
 721  */
 722 static int sjcd_ioctl( struct inode *ip, struct file *fp,
     /* [previous][next][first][last][top][bottom][index][help] */
 723                        unsigned int cmd, unsigned long arg ){
 724 #if defined( SJCD_TRACE )
 725   printk( "sjcd:ioctl\n" );
 726 #endif
 727 
 728   if( ip == NULL ) return( -EINVAL );
 729 
 730   sjcd_get_status();
 731   if( !sjcd_status_valid ) return( -EIO );
 732   if( sjcd_update_toc() < 0 ) return( -EIO );
 733 
 734   switch( cmd ){
 735   case CDROMSTART:{
 736 #if defined( SJCD_TRACE )
 737     printk( "sjcd: ioctl: start\n" );
 738 #endif
 739     return( 0 );
 740   }
 741 
 742   case CDROMSTOP:{
 743 #if defined( SJCD_TRACE )
 744     printk( "sjcd: ioctl: stop\n" );
 745 #endif
 746     sjcd_send_cmd( SCMD_PAUSE );
 747     ( void )sjcd_receive_status();
 748     sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
 749     return( 0 );
 750   }
 751 
 752   case CDROMPAUSE:{
 753     struct sjcd_hw_qinfo q_info;
 754 #if defined( SJCD_TRACE )
 755     printk( "sjcd: ioctl: pause\n" );
 756 #endif
 757     if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
 758       sjcd_send_cmd( SCMD_PAUSE );
 759       ( void )sjcd_receive_status();
 760       if( sjcd_get_q_info( &q_info ) < 0 ){
 761         sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
 762       } else {
 763         sjcd_audio_status = CDROM_AUDIO_PAUSED;
 764         sjcd_playing.start = q_info.abs;
 765       }
 766       return( 0 );
 767     } else return( -EINVAL );
 768   }
 769 
 770   case CDROMRESUME:{
 771 #if defined( SJCD_TRACE )
 772     printk( "sjcd: ioctl: resume\n" );
 773 #endif
 774     if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){
 775       /*
 776        * continue play starting at saved location
 777        */
 778       if( sjcd_play( &sjcd_playing ) < 0 ){
 779         sjcd_audio_status = CDROM_AUDIO_ERROR;
 780         return( -EIO );
 781       } else {
 782         sjcd_audio_status = CDROM_AUDIO_PLAY;
 783         return( 0 );
 784       }
 785     } else return( -EINVAL );
 786   }
 787 
 788   case CDROMPLAYTRKIND:{
 789     struct cdrom_ti ti; int s;
 790 #if defined( SJCD_TRACE )
 791     printk( "sjcd: ioctl: playtrkind\n" );
 792 #endif
 793     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){
 794       memcpy_fromfs( &ti, (void *)arg, sizeof( ti ) );
 795 
 796       if( ti.cdti_trk0 < sjcd_first_track_no ) return( -EINVAL );
 797       if( ti.cdti_trk1 > sjcd_last_track_no )
 798         ti.cdti_trk1 = sjcd_last_track_no;
 799       if( ti.cdti_trk0 > ti.cdti_trk1 ) return( -EINVAL );
 800 
 801       sjcd_playing.start = sjcd_table_of_contents[ ti.cdti_trk0 ].un.track_msf;
 802       sjcd_playing.end = ( ti.cdti_trk1 < sjcd_last_track_no ) ?
 803         sjcd_table_of_contents[ ti.cdti_trk1 + 1 ].un.track_msf :
 804           sjcd_table_of_contents[ 0 ].un.track_msf;
 805       
 806       if( sjcd_play( &sjcd_playing ) < 0 ){
 807         sjcd_audio_status = CDROM_AUDIO_ERROR;
 808         return( -EIO );
 809       } else sjcd_audio_status = CDROM_AUDIO_PLAY;
 810     }
 811     return( s );
 812   }
 813 
 814   case CDROMPLAYMSF:{
 815     struct cdrom_msf sjcd_msf; int s;
 816 #if defined( SJCD_TRACE )
 817     printk( "sjcd: ioctl: playmsf\n" );
 818 #endif
 819     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( sjcd_msf ) ) ) == 0 ){
 820       if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
 821         sjcd_send_cmd( SCMD_PAUSE );
 822         ( void )sjcd_receive_status();
 823         sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
 824       }
 825 
 826       memcpy_fromfs( &sjcd_msf, (void *)arg, sizeof( sjcd_msf ) );
 827 
 828       sjcd_playing.start.min = bin2bcd( sjcd_msf.cdmsf_min0 );
 829       sjcd_playing.start.sec = bin2bcd( sjcd_msf.cdmsf_sec0 );
 830       sjcd_playing.start.frame = bin2bcd( sjcd_msf.cdmsf_frame0 );
 831       sjcd_playing.end.min = bin2bcd( sjcd_msf.cdmsf_min1 );
 832       sjcd_playing.end.sec = bin2bcd( sjcd_msf.cdmsf_sec1 );
 833       sjcd_playing.end.frame = bin2bcd( sjcd_msf.cdmsf_frame1 );
 834 
 835       if( sjcd_play( &sjcd_playing ) < 0 ){
 836         sjcd_audio_status = CDROM_AUDIO_ERROR;
 837         return( -EIO );
 838       } else sjcd_audio_status = CDROM_AUDIO_PLAY;
 839     }
 840     return( s );
 841   }
 842 
 843   case CDROMREADTOCHDR:{
 844     struct cdrom_tochdr toc_header; int s;
 845 #if defined (SJCD_TRACE )
 846     printk( "sjcd: ioctl: readtocheader\n" );
 847 #endif
 848     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){
 849       toc_header.cdth_trk0 = sjcd_first_track_no;
 850       toc_header.cdth_trk1 = sjcd_last_track_no;
 851       memcpy_tofs( (void *)arg, &toc_header, sizeof( toc_header ) );
 852     }
 853     return( s );
 854   }
 855 
 856   case CDROMREADTOCENTRY:{
 857     struct cdrom_tocentry toc_entry; int s;
 858 #if defined( SJCD_TRACE )
 859     printk( "sjcd: ioctl: readtocentry\n" );
 860 #endif
 861     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){
 862       struct sjcd_hw_disk_info *tp;
 863 
 864       memcpy_fromfs( &toc_entry, (void *)arg, sizeof( toc_entry ) );
 865 
 866       if( toc_entry.cdte_track == CDROM_LEADOUT )
 867         tp = &sjcd_table_of_contents[ 0 ];
 868       else if( toc_entry.cdte_track < sjcd_first_track_no ) return( -EINVAL );
 869       else if( toc_entry.cdte_track > sjcd_last_track_no ) return( -EINVAL );
 870       else tp = &sjcd_table_of_contents[ toc_entry.cdte_track ];
 871 
 872       toc_entry.cdte_adr = tp->track_control & 0x0F;
 873       toc_entry.cdte_ctrl = tp->track_control >> 4;
 874 
 875       switch( toc_entry.cdte_format ){
 876       case CDROM_LBA:
 877         toc_entry.cdte_addr.lba = msf2hsg( &( tp->un.track_msf ) );
 878         break;
 879       case CDROM_MSF:
 880         toc_entry.cdte_addr.msf.minute = bcd2bin( tp->un.track_msf.min );
 881         toc_entry.cdte_addr.msf.second = bcd2bin( tp->un.track_msf.sec );
 882         toc_entry.cdte_addr.msf.frame = bcd2bin( tp->un.track_msf.frame );
 883         break;
 884       default: return( -EINVAL );
 885       }
 886       memcpy_tofs( (void *)arg, &toc_entry, sizeof( toc_entry ) );
 887     }
 888     return( s );
 889   }
 890 
 891   case CDROMSUBCHNL:{
 892     struct cdrom_subchnl subchnl; int s;
 893 #if defined( SJCD_TRACE )
 894     printk( "sjcd: ioctl: subchnl\n" );
 895 #endif
 896     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){
 897       struct sjcd_hw_qinfo q_info;
 898 
 899       memcpy_fromfs( &subchnl, (void *)arg, sizeof( subchnl ) );
 900       if( sjcd_get_q_info( &q_info ) < 0 ) return( -EIO );
 901 
 902       subchnl.cdsc_audiostatus = sjcd_audio_status;
 903       subchnl.cdsc_adr = q_info.track_control & 0x0F;
 904       subchnl.cdsc_ctrl = q_info.track_control >> 4;
 905       subchnl.cdsc_trk = bcd2bin( q_info.track_no );
 906       subchnl.cdsc_ind = bcd2bin( q_info.x );
 907 
 908       switch( subchnl.cdsc_format ){
 909       case CDROM_LBA:
 910         subchnl.cdsc_absaddr.lba = msf2hsg( &( q_info.abs ) );
 911         subchnl.cdsc_reladdr.lba = msf2hsg( &( q_info.rel ) );
 912         break;
 913       case CDROM_MSF:
 914         subchnl.cdsc_absaddr.msf.minute = bcd2bin( q_info.abs.min );
 915         subchnl.cdsc_absaddr.msf.second = bcd2bin( q_info.abs.sec );
 916         subchnl.cdsc_absaddr.msf.frame = bcd2bin( q_info.abs.frame );
 917         subchnl.cdsc_reladdr.msf.minute = bcd2bin( q_info.rel.min );
 918         subchnl.cdsc_reladdr.msf.second = bcd2bin( q_info.rel.sec );
 919         subchnl.cdsc_reladdr.msf.frame = bcd2bin( q_info.rel.frame );
 920         break;
 921       default: return( -EINVAL );
 922       }
 923       memcpy_tofs( (void *)arg, &subchnl, sizeof( subchnl ) );
 924     }
 925     return( s );
 926   }
 927 
 928   case CDROMVOLCTRL:{
 929     struct cdrom_volctrl vol_ctrl; int s;
 930 #if defined( SJCD_TRACE )
 931     printk( "sjcd: ioctl: volctrl\n" );
 932 #endif
 933     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){
 934       unsigned char dummy[ 4 ];
 935 
 936       memcpy_fromfs( &vol_ctrl, (void *)arg, sizeof( vol_ctrl ) );
 937       sjcd_send_4_cmd( SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF,
 938                       vol_ctrl.channel1, 0xFF );
 939       if( sjcd_receive_status() < 0 ) return( -EIO );
 940       ( void )sjcd_load_response( dummy, 4 );
 941     }
 942     return( s );
 943   }
 944 
 945   case CDROMEJECT:{
 946 #if defined( SJCD_TRACE )
 947     printk( "sjcd: ioctl: eject\n" );
 948 #endif
 949     if( !sjcd_command_is_in_progress ){
 950       sjcd_tray_unlock();
 951       sjcd_send_cmd( SCMD_EJECT_TRAY );
 952       ( void )sjcd_receive_status();
 953     }
 954     return( 0 );
 955   }
 956 
 957 #if defined( SJCD_GATHER_STAT )
 958   case 0xABCD:{
 959     int s;
 960 #if defined( SJCD_TRACE )
 961     printk( "sjcd: ioctl: statistic\n" );
 962 #endif
 963     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 )
 964       memcpy_tofs( (void *)arg, &statistic, sizeof( statistic ) );
 965     return( s );
 966   }
 967 #endif
 968 
 969   default:
 970     return( -EINVAL );
 971   }
 972 }
 973 
 974 /*
 975  * Invalidate internal buffers of the driver.
 976  */
 977 static void sjcd_invalidate_buffers( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 978   int i;
 979   for( i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[ i++ ] = -1 );
 980   sjcd_buf_out = -1;
 981 }
 982 
 983 /*
 984  * Take care of the different block sizes between cdrom and Linux.
 985  * When Linux gets variable block sizes this will probably go away.
 986  */
 987 
 988 #define CURRENT_IS_VALID                                      \
 989     ( CURRENT != NULL && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \
 990       CURRENT->cmd == READ && CURRENT->sector != -1 )
 991 
 992 static void sjcd_transfer( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
 993 #if defined( SJCD_TRACE )
 994   printk( "sjcd: transfer:\n" );
 995 #endif
 996   if( CURRENT_IS_VALID ){
 997     while( CURRENT->nr_sectors ){
 998       int i, bn = CURRENT->sector / 4;
 999       for( i = 0; i < SJCD_BUF_SIZ && sjcd_buf_bn[ i ] != bn; i++ );
1000       if( i < SJCD_BUF_SIZ ){
1001         int offs = ( i * 4 + ( CURRENT->sector & 3 ) ) * 512;
1002         int nr_sectors = 4 - ( CURRENT->sector & 3 );
1003         if( sjcd_buf_out != i ){
1004           sjcd_buf_out = i;
1005           if( sjcd_buf_bn[ i ] != bn ){
1006             sjcd_buf_out = -1;
1007             continue;
1008           }
1009         }
1010         if( nr_sectors > CURRENT->nr_sectors )
1011           nr_sectors = CURRENT->nr_sectors;
1012 #if defined( SJCD_TRACE )
1013         printk( "copy out\n" );
1014 #endif
1015         memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 );
1016         CURRENT->nr_sectors -= nr_sectors;
1017         CURRENT->sector += nr_sectors;
1018         CURRENT->buffer += nr_sectors * 512;
1019       } else {
1020         sjcd_buf_out = -1;
1021         break;
1022       }
1023     }
1024   }
1025 #if defined( SJCD_TRACE )
1026   printk( "sjcd: transfer: done\n" );
1027 #endif
1028 }
1029 
1030 static void sjcd_poll( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
1031 #if defined( SJCD_GATHER_STAT )
1032   /*
1033    * Update total number of ticks.
1034    */
1035   statistic.ticks++;
1036   statistic.tticks[ sjcd_transfer_state ]++;
1037 #endif
1038 
1039  ReSwitch: switch( sjcd_transfer_state ){
1040       
1041   case SJCD_S_IDLE:{
1042 #if defined( SJCD_GATHER_STAT )
1043     statistic.idle_ticks++;
1044 #endif
1045 #if defined( SJCD_TRACE )
1046     printk( "SJCD_S_IDLE\n" );
1047 #endif
1048     return;
1049   }
1050 
1051   case SJCD_S_START:{
1052 #if defined( SJCD_GATHER_STAT )
1053     statistic.start_ticks++;
1054 #endif
1055     sjcd_send_cmd( SCMD_GET_STATUS );
1056     sjcd_transfer_state =
1057       sjcd_mode == SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
1058     sjcd_transfer_timeout = 500;
1059 #if defined( SJCD_TRACE )
1060     printk( "SJCD_S_START: goto SJCD_S_%s mode\n",
1061            sjcd_transfer_state == SJCD_S_READ ? "READ" : "MODE" );
1062 #endif
1063     break;
1064   }
1065     
1066   case SJCD_S_MODE:{
1067     if( sjcd_check_status() ){
1068       /*
1069        * Previous command is completed.
1070        */
1071       if( !sjcd_status_valid || sjcd_command_failed ){
1072 #if defined( SJCD_TRACE )
1073         printk( "SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
1074 #endif
1075         sjcd_transfer_state = SJCD_S_STOP;
1076         goto ReSwitch;
1077       }
1078 
1079       sjcd_mode = 0; /* unknown mode; should not be valid when failed */
1080       sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_COOKED );
1081       sjcd_transfer_state = SJCD_S_READ; sjcd_transfer_timeout = 1000;
1082 #if defined( SJCD_TRACE )
1083       printk( "SJCD_S_MODE: goto SJCD_S_READ mode\n" );
1084 #endif
1085     }
1086 #if defined( SJCD_GATHER_STAT )
1087     else statistic.mode_ticks++;
1088 #endif
1089     break;
1090   }
1091 
1092   case SJCD_S_READ:{
1093     if( sjcd_status_valid ? 1 : sjcd_check_status() ){
1094       /*
1095        * Previos command is completed.
1096        */
1097       if( !sjcd_status_valid || sjcd_command_failed ){
1098 #if defined( SJCD_TRACE )
1099         printk( "SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
1100 #endif
1101         sjcd_transfer_state = SJCD_S_STOP;
1102         goto ReSwitch;
1103       }
1104       if( !sjcd_media_is_available ){
1105 #if defined( SJCD_TRACE )
1106         printk( "SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n" );
1107 #endif
1108         sjcd_transfer_state = SJCD_S_STOP;
1109         goto ReSwitch;
1110       }
1111       if( sjcd_mode != SCMD_MODE_COOKED ){
1112         /*
1113          * We seem to come from set mode. So discard one byte of result.
1114          */
1115         if( sjcd_load_response( &sjcd_mode, 1 ) != 0 ){
1116 #if defined( SJCD_TRACE )
1117           printk( "SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n" );
1118 #endif
1119           sjcd_transfer_state = SJCD_S_STOP;
1120           goto ReSwitch;
1121         }
1122         if( sjcd_mode != SCMD_MODE_COOKED ){
1123 #if defined( SJCD_TRACE )
1124           printk( "SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n" );
1125 #endif
1126           sjcd_transfer_state = SJCD_S_STOP;
1127           goto ReSwitch;
1128         }
1129       }
1130 
1131       if( CURRENT_IS_VALID ){
1132         struct sjcd_play_msf msf;
1133 
1134         sjcd_next_bn = CURRENT->sector / 4;
1135         hsg2msf( sjcd_next_bn, &msf.start );
1136         msf.end.min = 0; msf.end.sec = 0;            
1137         msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ;
1138 #if defined( SJCD_TRACE )
1139         printk( "---reading msf-address %x:%x:%x  %x:%x:%x\n",
1140                msf.start.min, msf.start.sec, msf.start.frame,
1141                msf.end.min,   msf.end.sec,   msf.end.frame );
1142         printk( "sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", \
1143              sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
1144              sjcd_buf_bn[ sjcd_buf_in ] );
1145 #endif  
1146         sjcd_send_6_cmd( SCMD_DATA_READ, &msf );
1147         sjcd_transfer_state = SJCD_S_DATA;
1148         sjcd_transfer_timeout = 500;
1149 #if defined( SJCD_TRACE )
1150         printk( "SJCD_S_READ: go to SJCD_S_DATA mode\n" );
1151 #endif
1152       } else {
1153 #if defined( SJCD_TRACE )
1154         printk( "SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n" );
1155 #endif
1156         sjcd_transfer_state = SJCD_S_STOP;
1157         goto ReSwitch;
1158       }
1159     }
1160 #if defined( SJCD_GATHER_STAT )
1161     else statistic.read_ticks++;
1162 #endif
1163     break;
1164   }
1165 
1166   case SJCD_S_DATA:{
1167     unsigned char stat;
1168 
1169   sjcd_s_data: stat = inb( SJCDPORT( 1 ) );
1170 #if defined( SJCD_TRACE )
1171     printk( "SJCD_S_DATA: status = 0x%02x\n", stat );
1172 #endif
1173     if( SJCD_STATUS_AVAILABLE( stat ) ){
1174       /*
1175        * No data is waiting for us in the drive buffer. Status of operation
1176        * completion is available. Read and parse it.
1177        */
1178       sjcd_load_status();
1179 
1180       if( !sjcd_status_valid || sjcd_command_failed ){
1181 #if defined( SJCD_TRACE )
1182         printk( "sjcd: read block %d failed, maybe audio disk? Giving up\n",
1183                sjcd_next_bn );
1184 #endif
1185         if( CURRENT_IS_VALID ) end_request( 0 );
1186 #if defined( SJCD_TRACE )
1187         printk( "SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n" );
1188 #endif
1189         sjcd_transfer_state = SJCD_S_STOP;
1190         goto ReSwitch;
1191       }
1192 
1193       if( !sjcd_media_is_available ){
1194         printk( "SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n" );
1195         sjcd_transfer_state = SJCD_S_STOP;
1196         goto ReSwitch;
1197       }
1198 
1199       sjcd_transfer_state = SJCD_S_READ;
1200       goto ReSwitch;
1201     } else if( SJCD_DATA_AVAILABLE( stat ) ){
1202       /*
1203        * One frame is read into device buffer. We must copy it to our memory.
1204        * Otherwise cdrom hangs up. Check to see if we have something to copy
1205        * to.
1206        */
1207       if( !CURRENT_IS_VALID && sjcd_buf_in == sjcd_buf_out ){
1208 #if defined( SJCD_TRACE )
1209         printk( "SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n" );
1210         printk( " ... all the date would be discarded\n" );
1211 #endif
1212         sjcd_transfer_state = SJCD_S_STOP;
1213         goto ReSwitch;
1214       }
1215 
1216       /*
1217        * Everything seems to be OK. Just read the frame and recalculate
1218        * indecis.
1219        */
1220       sjcd_buf_bn[ sjcd_buf_in ] = -1; /* ??? */
1221       insb( SJCDPORT( 2 ), sjcd_buf + 2048 * sjcd_buf_in, 2048 );
1222 #if defined( SJCD_TRACE )
1223       printk( "SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
1224              sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
1225              sjcd_buf_bn[ sjcd_buf_in ] );
1226 #endif
1227       sjcd_buf_bn[ sjcd_buf_in ] = sjcd_next_bn++;
1228       if( sjcd_buf_out == -1 ) sjcd_buf_out = sjcd_buf_in;
1229       if( ++sjcd_buf_in == SJCD_BUF_SIZ ) sjcd_buf_in = 0;
1230 
1231       /*
1232        * Only one frame is ready at time. So we should turn over to wait for
1233        * another frame. If we need that, of course.
1234        */
1235       if( --sjcd_read_count == 0 ){
1236         /*
1237          * OK, request seems to be precessed. Continue transferring...
1238          */
1239         if( !sjcd_transfer_is_active ){
1240           while( CURRENT_IS_VALID ){
1241             /*
1242              * Continue transferring.
1243              */
1244             sjcd_transfer();
1245             if( CURRENT->nr_sectors == 0 ) end_request( 1 );
1246             else break;
1247           }
1248         }
1249         if( CURRENT_IS_VALID &&
1250            ( CURRENT->sector / 4 < sjcd_next_bn ||
1251             CURRENT->sector / 4 > sjcd_next_bn + SJCD_BUF_SIZ ) ){
1252 #if defined( SJCD_TRACE )
1253           printk( "SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n" );
1254 #endif
1255           sjcd_transfer_state = SJCD_S_STOP;
1256           goto ReSwitch;
1257         }
1258       }
1259       /*
1260        * Now we should turn around rather than wait for while.
1261        */
1262       goto sjcd_s_data;
1263     }
1264 #if defined( SJCD_GATHER_STAT )
1265     else statistic.data_ticks++;
1266 #endif
1267     break;
1268   }
1269 
1270   case SJCD_S_STOP:{
1271     sjcd_read_count = 0;
1272     sjcd_send_cmd( SCMD_STOP );
1273     sjcd_transfer_state = SJCD_S_STOPPING;
1274     sjcd_transfer_timeout = 500;
1275 #if defined( SJCD_GATHER_STAT )
1276     statistic.stop_ticks++;
1277 #endif
1278     break;
1279   }
1280 
1281   case SJCD_S_STOPPING:{
1282     unsigned char stat;
1283     
1284     stat = inb( SJCDPORT( 1 ) );
1285 #if defined( SJCD_TRACE )
1286     printk( "SJCD_S_STOP: status = 0x%02x\n", stat );
1287 #endif      
1288     if( SJCD_DATA_AVAILABLE( stat ) ){
1289       int i;
1290 #if defined( SJCD_TRACE )
1291       printk( "SJCD_S_STOP: discard data\n" );
1292 #endif
1293       /*
1294        * Discard all the data from the pipe. Foolish method.
1295        */
1296       for( i = 2048; i--; ( void )inb( SJCDPORT( 2 ) ) );
1297       sjcd_transfer_timeout = 500;
1298     } else if( SJCD_STATUS_AVAILABLE( stat ) ){
1299       sjcd_load_status();
1300       if( sjcd_status_valid && sjcd_media_is_changed ) {
1301         sjcd_toc_uptodate = 0;
1302         sjcd_invalidate_buffers();
1303       }
1304       if( CURRENT_IS_VALID ){
1305         if( sjcd_status_valid ) sjcd_transfer_state = SJCD_S_READ;
1306         else sjcd_transfer_state = SJCD_S_START;
1307       } else sjcd_transfer_state = SJCD_S_IDLE;
1308       goto ReSwitch;
1309     }
1310 #if defined( SJCD_GATHER_STAT )
1311     else statistic.stopping_ticks++;
1312 #endif
1313     break;
1314   }
1315 
1316   default:
1317     printk( "sjcd_poll: invalid state %d\n", sjcd_transfer_state );
1318     return;
1319   }
1320   
1321   if( --sjcd_transfer_timeout == 0 ){
1322     printk( "sjcd: timeout in state %d\n", sjcd_transfer_state );
1323     while( CURRENT_IS_VALID ) end_request( 0 );
1324     sjcd_send_cmd( SCMD_STOP );
1325     sjcd_transfer_state = SJCD_S_IDLE;
1326     goto ReSwitch;
1327     }
1328 
1329   /*
1330    * Get back in some time. 1 should be replaced with count variable to
1331    * avoid unnecessary testings.
1332    */
1333   SJCD_SET_TIMER( sjcd_poll, 1 );
1334 }
1335 
1336 static void do_sjcd_request( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
1337 #if defined( SJCD_TRACE )
1338   printk( "sjcd: do_sjcd_request(%ld+%ld)\n",
1339          CURRENT->sector, CURRENT->nr_sectors );
1340 #endif
1341   sjcd_transfer_is_active = 1;
1342   while( CURRENT_IS_VALID ){
1343     /*
1344      * Who of us are paranoic?
1345      */
1346     if( CURRENT->bh && !( CURRENT->bh->b_lock ) )
1347       panic( DEVICE_NAME ": block not locked" );
1348 
1349     sjcd_transfer();
1350     if( CURRENT->nr_sectors == 0 ) end_request( 1 );
1351     else {
1352       sjcd_buf_out = -1;         /* Want to read a block not in buffer */
1353       if( sjcd_transfer_state == SJCD_S_IDLE ){
1354         if( !sjcd_toc_uptodate ){
1355           if( sjcd_update_toc() < 0 ){
1356             printk( "sjcd: transfer: discard\n" );
1357             while( CURRENT_IS_VALID ) end_request( 0 );
1358             break;
1359           }
1360         }
1361         sjcd_transfer_state = SJCD_S_START;
1362         SJCD_SET_TIMER( sjcd_poll, HZ/100 );
1363       }
1364       break;
1365     }
1366   }
1367   sjcd_transfer_is_active = 0;
1368 #if defined( SJCD_TRACE )
1369   printk( "sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
1370          sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[ sjcd_buf_in ] );
1371   printk( "do_sjcd_request ends\n" );
1372 #endif
1373 }
1374 
1375 /*
1376  * Open the device special file. Check disk is in.
1377  */
1378 int sjcd_open( struct inode *ip, struct file *fp ){
     /* [previous][next][first][last][top][bottom][index][help] */
1379   /*
1380    * Check the presence of device.
1381    */
1382   if( !sjcd_present ) return( -ENXIO );
1383   
1384   /*
1385    * Only read operations are allowed. Really? (:-)
1386    */
1387   if( fp->f_mode & 2 ) return( -EROFS );
1388   
1389   if( sjcd_open_count == 0 ){
1390     int s, sjcd_open_tries;
1391 /* We don't know that, do we? */
1392 /*
1393     sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
1394 */
1395     sjcd_mode = 0;
1396     sjcd_door_was_open = 0;
1397     sjcd_transfer_state = SJCD_S_IDLE;
1398     sjcd_invalidate_buffers();
1399     sjcd_status_valid = 0;
1400 
1401     /*
1402      * Strict status checking.
1403      */
1404     for( sjcd_open_tries = 4; --sjcd_open_tries; ){
1405       if( !sjcd_status_valid ) sjcd_get_status();
1406       if( !sjcd_status_valid ){
1407 #if defined( SJCD_DIAGNOSTIC )
1408         printk( "sjcd: open: timed out when check status.\n" );
1409 #endif
1410         return( -EIO );
1411       } else if( !sjcd_media_is_available ){
1412 #if defined( SJCD_DIAGNOSTIC )
1413         printk("sjcd: open: no disk in drive\n");
1414 #endif
1415         if( !sjcd_door_closed ){
1416           sjcd_door_was_open = 1;
1417 #if defined( SJCD_TRACE )
1418           printk("sjcd: open: close the tray\n");
1419 #endif
1420           s = sjcd_tray_close();
1421           if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
1422 #if defined( SJCD_DIAGNOSTIC )
1423             printk("sjcd: open: tray close attempt failed\n");
1424 #endif
1425             return( -EIO );
1426           }
1427           continue;
1428         } else return( -EIO );
1429       }
1430       break;
1431     }
1432     s = sjcd_tray_lock();
1433     if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
1434 #if defined( SJCD_DIAGNOSTIC )
1435       printk("sjcd: open: tray lock attempt failed\n");
1436 #endif
1437       return( -EIO );
1438     }
1439 #if defined( SJCD_TRACE )
1440     printk( "sjcd: open: done\n" );
1441 #endif
1442   }
1443 #ifdef MODULE
1444   MOD_INC_USE_COUNT;
1445 #endif
1446   ++sjcd_open_count;
1447   return( 0 );
1448 }
1449 
1450 /*
1451  * On close, we flush all sjcd blocks from the buffer cache.
1452  */
1453 static void sjcd_release( struct inode *inode, struct file *file ){
     /* [previous][next][first][last][top][bottom][index][help] */
1454   int s;
1455 
1456 #if defined( SJCD_TRACE )
1457   printk( "sjcd: release\n" );
1458 #endif
1459 #ifdef MODULE
1460   MOD_DEC_USE_COUNT;
1461 #endif
1462   if( --sjcd_open_count == 0 ){
1463     sjcd_invalidate_buffers();
1464     sync_dev( inode->i_rdev );
1465     invalidate_buffers( inode->i_rdev );
1466     s = sjcd_tray_unlock();
1467     if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
1468 #if defined( SJCD_DIAGNOSTIC )
1469       printk("sjcd: release: tray unlock attempt failed.\n");
1470 #endif
1471     }
1472     if( sjcd_door_was_open ){
1473       s = sjcd_tray_open();
1474       if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
1475 #if defined( SJCD_DIAGNOSTIC )
1476         printk("sjcd: release: tray unload attempt failed.\n");
1477 #endif
1478       }
1479     }
1480   }
1481 }
1482 
1483 /*
1484  * A list of file operations allowed for this cdrom.
1485  */
1486 static struct file_operations sjcd_fops = {
1487   NULL,               /* lseek - default */
1488   block_read,         /* read - general block-dev read */
1489   block_write,        /* write - general block-dev write */
1490   NULL,               /* readdir - bad */
1491   NULL,               /* select */
1492   sjcd_ioctl,         /* ioctl */
1493   NULL,               /* mmap */
1494   sjcd_open,          /* open */
1495   sjcd_release,       /* release */
1496   NULL,               /* fsync */
1497   NULL,               /* fasync */
1498   sjcd_disk_change,   /* media change */
1499   NULL                /* revalidate */
1500 };
1501 
1502 /*
1503  * Following stuff is intended for initialization of the cdrom. It
1504  * first looks for presence of device. If the device is present, it
1505  * will be reset. Then read the version of the drive and load status.
1506  * The version is two BCD-coded bytes.
1507  */
1508 static struct {
1509   unsigned char major, minor;
1510 } sjcd_version;
1511 
1512 /*
1513  * Test for presence of drive and initialize it. Called at boot time.
1514  * Probe cdrom, find out version and status.
1515  */
1516 int sjcd_init( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
1517   int i;
1518 
1519   if ( (isp16_type=isp16_detect()) < 0 )
1520     printk( "No ISP16 cdrom interface found.\n" );
1521   else {
1522     u_char expected_drive;
1523 
1524     printk( "ISP16 cdrom interface (with OPTi 82C92%s chip) detected.\n",
1525       (isp16_type==2)?"9":"8" );
1526 
1527     printk( "ISP16 sound configuration.\n" );
1528     isp16_sound_config();
1529 
1530     expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
1531 
1532     if ( isp16_cdi_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) {
1533       printk( "ISP16 cdrom interface has not been properly configured.\n" );
1534       return( -EIO );
1535     }
1536   }
1537 
1538 #if defined( SJCD_TRACE )
1539   printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq );
1540 #endif  
1541 
1542   if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
1543     printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
1544     return( -EIO );
1545   }
1546   
1547   blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
1548   read_ahead[ MAJOR_NR ] = 4;
1549   
1550   if( check_region( sjcd_port, 4 ) ){
1551     printk( "Init failed, I/O port (%X) is already in use\n",
1552       sjcd_port );
1553     return( -EIO );
1554   }
1555   
1556   /*
1557    * Check for card. Since we are booting now, we can't use standard
1558    * wait algorithm.
1559    */
1560   printk( "Sanyo: Resetting: " );
1561   sjcd_send_cmd( SCMD_RESET );
1562   for( i = 1000; i-- > 0 && !sjcd_status_valid; ){
1563     unsigned long timer;
1564 
1565     /*
1566      * Wait 10ms approx.
1567      */
1568     for( timer = jiffies; jiffies <= timer; );
1569     if ( (i % 100) == 0 ) printk( "." );
1570     ( void )sjcd_check_status();
1571   }
1572   if( i == 0 || sjcd_command_failed ){
1573     printk( " reset failed, no drive found.\n" );
1574     return( -EIO );
1575   } else printk( "\n" );
1576 
1577   /*
1578    * Get and print out cdrom version.
1579    */
1580   printk( "Sanyo: Getting version: " );
1581   sjcd_send_cmd( SCMD_GET_VERSION );
1582   for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
1583     unsigned long timer;
1584 
1585     /*
1586      * Wait 10ms approx.
1587      */
1588     for( timer = jiffies; jiffies <= timer; );
1589     if ( (i % 100) == 0 ) printk( "." );
1590     ( void )sjcd_check_status();
1591   }
1592   if( i == 0 || sjcd_command_failed ){
1593     printk( " get version failed, no drive found.\n" );
1594     return( -EIO );
1595   }
1596 
1597   if( sjcd_load_response( &sjcd_version, sizeof( sjcd_version ) ) == 0 ){
1598     printk( " %1x.%02x\n", ( int )sjcd_version.major,
1599              ( int )sjcd_version.minor );
1600   } else {
1601     printk( " read version failed, no drive found.\n" );
1602     return( -EIO );
1603   }
1604 
1605   /*
1606    * Check and print out the tray state. (if it is needed?).
1607    */
1608   if( !sjcd_status_valid ){
1609     printk( "Sanyo: Getting status: " );
1610     sjcd_send_cmd( SCMD_GET_STATUS );
1611     for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
1612       unsigned long timer;
1613 
1614       /*
1615        * Wait 10ms approx.
1616        */
1617       for( timer = jiffies; jiffies <= timer; );
1618       if ( (i % 100) == 0 ) printk( "." );
1619       ( void )sjcd_check_status();
1620     }
1621     if( i == 0 || sjcd_command_failed ){
1622       printk( " get status failed, no drive found.\n" );
1623       return( -EIO );
1624     } else printk( "\n" );
1625   }
1626 
1627   printk( "SANYO CDR-H94A: Status: port=0x%x, irq=%d, dma=%d.\n",
1628          sjcd_port, sjcd_irq, sjcd_dma );
1629 
1630   sjcd_present++;
1631   return( 0 );
1632 }
1633 
1634 #ifdef MODULE
1635 void cleanup_module( void ){
     /* [previous][next][first][last][top][bottom][index][help] */
1636   if( MOD_IN_USE ){
1637     printk( "sjcd: module: in use - can not remove.\n" );
1638   } else if( ( unregister_blkdev( MAJOR_NR, "sjcd" ) == -EINVAL ) ){
1639     printk( "sjcd: module: can not unregister device.\n" );
1640   } else {
1641     release_region( sjcd_port, 4 );
1642     printk( "sjcd: module: removed.\n");
1643   }
1644 }
1645 #endif
1646 
1647 /*
1648  * -- ISP16 detection and configuration
1649  *
1650  *    Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
1651  *
1652  *    Version 0.5
1653  *
1654  *    Detect cdrom interface on ISP16 soundcard.
1655  *    Configure cdrom interface.
1656  *    Configure sound interface.
1657  *
1658  *    Algorithm for the card with OPTi 82C928 taken
1659  *    from the CDSETUP.SYS driver for MSDOS,
1660  *    by OPTi Computers, version 2.03.
1661  *    Algorithm for the card with OPTi 82C929 as communicated
1662  *    to me by Vadim Model and Leo Spiekman.
1663  *
1664  *    Use, modifification or redistribution of this software is
1665  *    allowed under the terms of the GPL.
1666  *
1667  */
1668 
1669 
1670 #define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
1671 #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
1672 
1673 static short
1674 isp16_detect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1675 {
1676 
1677   if ( !( isp16_c929__detect() < 0 ) )
1678     return(2);
1679   else
1680     return( isp16_c928__detect() );
1681 }
1682 
1683 static short
1684 isp16_c928__detect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1685 {
1686   u_char ctrl;
1687   u_char enable_cdrom;
1688   u_char io;
1689   short i = -1;
1690 
1691   isp16_ctrl = ISP16_C928__CTRL;
1692   isp16_enable_port = ISP16_C928__ENABLE_PORT;
1693 
1694   /* read' and write' are a special read and write, respectively */
1695 
1696   /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
1697   ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
1698   ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1699 
1700   /* read' 3,4 and 5-bit from the cdrom enable port */
1701   enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
1702 
1703   if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
1704     /* read' last 2 bits of ISP16_IO_SET_PORT */
1705     io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
1706     if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
1707       if ( io == 0 ) {  /* ...the same and 0 */
1708         i = 0;
1709         enable_cdrom |= 0x20;
1710       }
1711       else {  /* ...the same and 1 */  /* my card, first time 'round */
1712         i = 1;
1713         enable_cdrom |= 0x28;
1714       }
1715       ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
1716     }
1717     else {  /* bits are not the same */
1718       ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1719       return(i); /* -> not detected: possibly incorrect conclusion */
1720     }
1721   }
1722   else if ( enable_cdrom == 0x20 )
1723     i = 0;
1724   else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
1725     i = 1;
1726 
1727   ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1728 
1729   return(i);
1730 }
1731 
1732 static short
1733 isp16_c929__detect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1734 {
1735   u_char ctrl;
1736   u_char tmp;
1737 
1738   isp16_ctrl = ISP16_C929__CTRL;
1739   isp16_enable_port = ISP16_C929__ENABLE_PORT;
1740 
1741   /* read' and write' are a special read and write, respectively */
1742 
1743   /* read' ISP16_CTRL_PORT and save */
1744   ctrl = ISP16_IN( ISP16_CTRL_PORT );
1745 
1746   /* write' zero to the ctrl port and get response */
1747   ISP16_OUT( ISP16_CTRL_PORT, 0 );
1748   tmp = ISP16_IN( ISP16_CTRL_PORT );
1749 
1750   if ( tmp != 2 )  /* isp16 with 82C929 not detected */
1751     return(-1);
1752 
1753   /* restore ctrl port value */
1754   ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1755   
1756   return(2);
1757 }
1758 
1759 static short
1760 isp16_cdi_config( int base, u_char drive_type, int irq, int dma )
     /* [previous][next][first][last][top][bottom][index][help] */
1761 {
1762   u_char base_code;
1763   u_char irq_code;
1764   u_char dma_code;
1765   u_char i;
1766 
1767   if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
1768     printk( "Mitsumi cdrom drive has no dma support.\n" );
1769 
1770   switch (base) {
1771   case 0x340: base_code = ISP16_BASE_340; break;
1772   case 0x330: base_code = ISP16_BASE_330; break;
1773   case 0x360: base_code = ISP16_BASE_360; break;
1774   case 0x320: base_code = ISP16_BASE_320; break;
1775   default:
1776     printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
1777     return(-1);
1778   }
1779   switch (irq) {
1780   case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
1781   case 5: irq_code = ISP16_IRQ_5;
1782           printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
1783             " due to possible conflicts with the soundcard.\n");
1784           break;
1785   case 7: irq_code = ISP16_IRQ_7;
1786           printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
1787             " due to possible conflicts with the soundcard.\n");
1788           break;
1789   case 3: irq_code = ISP16_IRQ_3; break;
1790   case 9: irq_code = ISP16_IRQ_9; break;
1791   case 10: irq_code = ISP16_IRQ_10; break;
1792   case 11: irq_code = ISP16_IRQ_11; break;
1793   default:
1794     printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
1795     return(-1);
1796   }
1797   switch (dma) {
1798   case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
1799   case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
1800             " due to conflict with the soundcard.\n");
1801           return(-1); break;
1802   case 3: dma_code = ISP16_DMA_3; break;
1803   case 5: dma_code = ISP16_DMA_5; break;
1804   case 6: dma_code = ISP16_DMA_6; break;
1805   case 7: dma_code = ISP16_DMA_7; break;
1806   default:
1807     printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
1808     return(-1);
1809   }
1810 
1811   if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
1812     drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
1813     drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
1814     drive_type != ISP16_DRIVE_X ) {
1815     printk( "Drive type (code 0x%02X) not supported by cdrom"
1816      " interface on ISP16.\n", drive_type );
1817     return(-1);
1818   }
1819 
1820   /* set type of interface */
1821   i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
1822   ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
1823 
1824   /* enable cdrom on interface with 82C929 chip */
1825   if ( isp16_type > 1 )
1826     ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
1827 
1828   /* set base address, irq and dma */
1829   i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
1830   ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
1831 
1832   return(0);
1833 }
1834 
1835 static void isp16_sound_config( void )
     /* [previous][next][first][last][top][bottom][index][help] */
1836 {
1837   int i;
1838   u_char saved;
1839 
1840   saved = ISP16_IN( 0xF8D ) & 0x8F;
1841     
1842   ISP16_OUT( 0xF8D, 0x40 );
1843 
1844   /*
1845    * Now we should wait for a while...
1846    */
1847   for( i = 16*1024; i--; );
1848   
1849   ISP16_OUT( 0xF8D, saved );
1850 
1851   ISP16_OUT( 0xF91, 0x1B );
1852 
1853   for( i = 5*64*1024; i != 0; i-- )
1854     if( !( inb( 0x534 ) & 0x80 ) ) break;
1855 
1856   if( i > 0 ) {
1857     saved = ( inb( 0x534 ) & 0xE0 ) | 0x0A;
1858     outb( saved, 0x534 );
1859 
1860     special_mask = ( inb( 0x535 ) >> 4 ) & 0x08;
1861 
1862     saved = ( inb( 0x534 ) & 0xE0 ) | 0x0C;
1863     outb( saved, 0x534 );
1864 
1865     switch( inb( 0x535 ) ) {
1866       case 0x09:
1867       case 0x0A:
1868         special_mask |= 0x05;
1869         break;
1870       case 0x8A:
1871         special_mask = 0x0F;
1872         break;
1873       default:
1874         i = 0;
1875     }
1876   }
1877   if ( i == 0 ) {
1878     printk( "Strange MediaMagic, but\n" );
1879   }
1880   else {
1881     printk( "Conf:" );
1882     saved = inb( 0x534 ) & 0xE0;
1883     for( i = 0; i < 16; i++ ) {
1884       outb( 0x20 | ( u_char )i, 0x534 );
1885       outb( defaults[i], 0x535 );
1886     }
1887     for ( i = 0; i < 16; i++ ) {
1888       outb( 0x20 | ( u_char )i, 0x534 );
1889       saved = inb( 0x535 );
1890       printk( " %02X", saved );
1891     }
1892     printk( "\n" );
1893   }
1894 
1895   ISP16_OUT( 0xF91, 0xA0 | special_mask );
1896 
1897   /*
1898    * The following have no explaination yet.
1899    */
1900   ISP16_OUT( 0xF90, 0xA2 );
1901   ISP16_OUT( 0xF92, 0x03 );
1902 
1903   /*
1904    * Turn general sound on and set total volume.
1905    */
1906   ISP16_OUT( 0xF93, 0x0A );
1907 
1908 /*
1909   outb( 0x04, 0x224 );
1910   saved = inb( 0x225 );
1911   outb( 0x04, 0x224 );
1912   outb( saved, 0x225 );
1913 */
1914 
1915 }

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