OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [cdrom/] [sjcd.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.