root/drivers/block/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_ioctl
  22. sjcd_interrupt
  23. sjcd_invalidate_buffers
  24. sjcd_transfer
  25. sjcd_poll
  26. do_sjcd_request
  27. sjcd_open
  28. sjcd_release
  29. sjcd_init
  30. isp16_detect
  31. isp16_no_ide__detect
  32. isp16_with_ide__detect
  33. isp16_config

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

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