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 }