This source file includes following definitions.
- sjcd_setup
 
- bin2bcd
 
- bcd2bin
 
- msf2hsg
 
- hsg2msf
 
- sjcd_send_cmd
 
- sjcd_send_1_cmd
 
- sjcd_send_4_cmd
 
- sjcd_send_6_cmd
 
- sjcd_load_response
 
- sjcd_load_status
 
- sjcd_check_status
 
- sjcd_status_timer
 
- sjcd_wait_for_status
 
- sjcd_receive_status
 
- sjcd_get_status
 
- sjcd_disk_change
 
- sjcd_update_toc
 
- sjcd_get_q_info
 
- sjcd_play
 
- sjcd_tray_close
 
- sjcd_tray_lock
 
- sjcd_tray_unlock
 
- sjcd_tray_open
 
- sjcd_ioctl
 
- sjcd_invalidate_buffers
 
- sjcd_transfer
 
- sjcd_poll
 
- do_sjcd_request
 
- sjcd_open
 
- sjcd_release
 
- sjcd_init
 
- init_module
 
- cleanup_module
 
- isp16_detect
 
- isp16_c928__detect
 
- isp16_c929__detect
 
- isp16_cdi_config
 
- isp16_sound_config
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  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 
  76 
  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  
  85 #define ISP16_DRIVE_SET_MASK 0xF1  
  86 
  87 #define ISP16_DRIVE_SET_PORT 0xF8D
  88 
  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  
  95 #define ISP16_IRQ_7  0x08  
  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  
 106 
 107 #define ISP16_IO_SET_PORT  0xF8E
 108 
 109 #define ISP16_C928__ENABLE_PORT  0xF90  
 110 #define ISP16_C929__ENABLE_PORT  0xF91  
 111 #define ISP16_ENABLE_CDROM  0x80  
 112 
 113 
 114 #define ISP16_CTRL_PORT  0xF8F
 115 #define ISP16_C928__CTRL  0xE2  
 116 #define ISP16_C929__CTRL  0xE3  
 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; 
 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 
 136 
 137 
 138 
 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 
 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 
 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 
 194 
 195 static struct sjcd_stat statistic;
 196 #endif
 197 
 198 
 199 
 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 
 212 
 213 
 214 void sjcd_setup( char *str, int *ints )
     
 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 
 226 
 227 static unsigned char bin2bcd( int bin ){
     
 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 ){
     
 235     return( ( bcd >> 4 ) * 10 + ( bcd & 0x0F ) );
 236 }
 237 
 238 static long msf2hsg( struct msf *mp ){
     
 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 ){
     
 244   hsg += 150; msf->min = hsg / 4500;
 245   hsg %= 4500; msf->sec = hsg / 75; msf->frame = hsg % 75;
 246   msf->min = bin2bcd( msf->min );       
 247   msf->sec = bin2bcd( msf->sec );
 248   msf->frame = bin2bcd( msf->frame );
 249 }
 250 
 251 
 252 
 253 
 254 static void sjcd_send_cmd( unsigned char cmd ){
     
 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 
 266 
 267 static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){
     
 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 
 280 
 281 static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a,
     
 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 
 298 
 299 static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){
     
 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 
 317 
 318 
 319 static int sjcd_load_response( void *buf, int len ){
     
 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 
 333 
 334 
 335 static void sjcd_load_status( void ){
     
 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 
 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 
 359 
 360   sjcd_status_valid = 1, sjcd_error_reported = 0;
 361   sjcd_command_is_in_progress = 0;
 362 
 363   
 364 
 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 
 375 
 376 static int sjcd_check_status( void ){
     
 377   
 378 
 379 
 380   if( SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ){
 381     sjcd_load_status();
 382     return( 1 );
 383   } else {
 384     
 385 
 386 
 387     return( 0 );
 388   }
 389 }
 390 
 391 
 392 
 393 
 394 static volatile long sjcd_status_timeout;
 395 
 396 
 397 
 398 
 399 
 400 
 401 #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
 402 
 403 static void sjcd_status_timer( void ){
     
 404   if( sjcd_check_status() ){
 405     
 406 
 407 
 408     wake_up( &sjcd_waitq );
 409   } else if( --sjcd_status_timeout <= 0 ){
 410     
 411 
 412 
 413     wake_up( &sjcd_waitq );
 414   } else {
 415     
 416 
 417 
 418     SJCD_SET_TIMER( sjcd_status_timer, 1 );
 419   }
 420 }
 421 
 422 
 423 
 424 
 425 
 426 static int sjcd_wait_for_status( void ){
     
 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 ){
     
 438   int i;
 439 #if defined( SJCD_TRACE )
 440   printk( "sjcd: receive_status\n" );
 441 #endif
 442   
 443 
 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 
 459 
 460 static void sjcd_get_status( void ){
     
 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 
 470 
 471 static int sjcd_disk_change( kdev_t full_dev ){
     
 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 
 486 
 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 ){
     
 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 
 500 
 501   if( sjcd_toc_uptodate ) return( 0 );
 502 
 503   
 504 
 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 
 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 
 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 
 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 
 627 
 628 static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){
     
 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 
 650 
 651 static int sjcd_play( struct sjcd_play_msf *mp ){
     
 652   struct sjcd_play_msf msf;
 653 
 654   
 655 
 656 
 657   sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_PLAY );
 658   if( sjcd_receive_status() < 0 ) return( -1 );
 659 
 660   
 661 
 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 
 670 
 671   sjcd_send_6_cmd( SCMD_PLAY, mp );
 672   return( sjcd_receive_status() );
 673 }
 674 
 675 
 676 
 677 
 678 static int sjcd_tray_close( void ){
     
 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 ){
     
 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 ){
     
 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 ){
     
 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 
 712 
 713 static int sjcd_ioctl( struct inode *ip, struct file *fp,
     
 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 
 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 
 967 
 968 static void sjcd_invalidate_buffers( void ){
     
 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 
 976 
 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 ){
     
 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 ){
     
1022 #if defined( SJCD_GATHER_STAT )
1023   
1024 
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 
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; 
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 
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 
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 
1167 
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 
1195 
1196 
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 
1209 
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 
1224 
1225 
1226       if( --sjcd_read_count == 0 ){
1227         
1228 
1229 
1230         if( !sjcd_transfer_is_active ){
1231           while( CURRENT_IS_VALID ){
1232             
1233 
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 
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 
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 
1322 
1323 
1324   SJCD_SET_TIMER( sjcd_poll, 1 );
1325 }
1326 
1327 static void do_sjcd_request( void ){
     
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 
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;         
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 
1368 
1369 int sjcd_open( struct inode *ip, struct file *fp ){
     
1370   
1371 
1372 
1373   if( !sjcd_present ) return( -ENXIO );
1374   
1375   
1376 
1377 
1378   if( fp->f_mode & 2 ) return( -EROFS );
1379   
1380   if( sjcd_open_count == 0 ){
1381     int s, sjcd_open_tries;
1382 
1383 
1384 
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 
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 
1441 
1442 static void sjcd_release( struct inode *inode, struct file *file ){
     
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 
1472 
1473 static struct file_operations sjcd_fops = {
1474   NULL,               
1475   block_read,         
1476   block_write,        
1477   NULL,               
1478   NULL,               
1479   sjcd_ioctl,         
1480   NULL,               
1481   sjcd_open,          
1482   sjcd_release,       
1483   NULL,               
1484   NULL,               
1485   sjcd_disk_change,   
1486   NULL                
1487 };
1488 
1489 
1490 
1491 
1492 
1493 
1494 
1495 static struct {
1496   unsigned char major, minor;
1497 } sjcd_version;
1498 
1499 
1500 
1501 
1502 
1503 int sjcd_init( void ){
     
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 
1545 
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 
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 
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 
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 
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 
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)
     
1624 {
1625         return sjcd_init();
1626 }
1627 
1628 void cleanup_module( void ){
     
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 
1640 
1641 
1642 
1643 
1644 
1645 
1646 
1647 
1648 
1649 
1650 
1651 
1652 
1653 
1654 
1655 
1656 
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)
     
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)
     
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   
1686 
1687   
1688   ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
1689   ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1690 
1691   
1692   enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
1693 
1694   if ( !(enable_cdrom & 0x20) ) {  
1695     
1696     io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
1697     if ( ((io&0x01)<<1) == (io&0x02) ) {  
1698       if ( io == 0 ) {  
1699         i = 0;
1700         enable_cdrom |= 0x20;
1701       }
1702       else {    
1703         i = 1;
1704         enable_cdrom |= 0x28;
1705       }
1706       ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
1707     }
1708     else {  
1709       ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1710       return(i); 
1711     }
1712   }
1713   else if ( enable_cdrom == 0x20 )
1714     i = 0;
1715   else if ( enable_cdrom == 0x28 )  
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)
     
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   
1733 
1734   
1735   ctrl = ISP16_IN( ISP16_CTRL_PORT );
1736 
1737   
1738   ISP16_OUT( ISP16_CTRL_PORT, 0 );
1739   tmp = ISP16_IN( ISP16_CTRL_PORT );
1740 
1741   if ( tmp != 2 )  
1742     return(-1);
1743 
1744   
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 )
     
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; 
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;  
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   
1812   i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  
1813   ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
1814 
1815   
1816   if ( isp16_type > 1 )
1817     ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
1818 
1819   
1820   i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  
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 )
     
1827 {
1828   int i;
1829   u_char saved;
1830 
1831   saved = ISP16_IN( 0xF8D ) & 0x8F;
1832     
1833   ISP16_OUT( 0xF8D, 0x40 );
1834 
1835   
1836 
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 
1890 
1891   ISP16_OUT( 0xF90, 0xA2 );
1892   ISP16_OUT( 0xF92, 0x03 );
1893 
1894   
1895 
1896 
1897   ISP16_OUT( 0xF93, 0x0A );
1898 
1899 
1900 
1901 
1902 
1903 
1904 
1905 
1906 }