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

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