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_ioctl
- sjcd_interrupt
- sjcd_invalidate_buffers
- sjcd_transfer
- sjcd_poll
- do_sjcd_request
- sjcd_open
- sjcd_release
- sjcd_init
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 #include <linux/errno.h>
35 #include <linux/signal.h>
36 #include <linux/sched.h>
37 #include <linux/mm.h>
38 #include <linux/timer.h>
39 #include <linux/fs.h>
40 #include <linux/kernel.h>
41 #include <linux/cdrom.h>
42 #include <linux/ioport.h>
43 #include <linux/string.h>
44 #include <linux/delay.h>
45
46 #include <asm/system.h>
47 #include <asm/io.h>
48 #include <asm/segment.h>
49
50 #define MAJOR_NR SANYO_CDROM_MAJOR
51 #include "blk.h"
52 #ifdef CONFIG_ISP_16
53 #include <linux/isp16.h>
54 #endif
55 #include <linux/sjcd.h>
56
57 static int sjcd_present = 0;
58
59 #define SJCD_BUF_SIZ 32
60
61
62
63
64 static char sjcd_buf[ 2048 * SJCD_BUF_SIZ ];
65 static volatile int sjcd_buf_bn[ SJCD_BUF_SIZ ], sjcd_next_bn;
66 static volatile int sjcd_buf_in, sjcd_buf_out = -1;
67
68
69
70
71 static unsigned short sjcd_status_valid = 0;
72 static unsigned short sjcd_door_closed;
73 static unsigned short sjcd_media_is_available;
74 static unsigned short sjcd_media_is_changed;
75 static unsigned short sjcd_toc_uptodate = 0;
76 static unsigned short sjcd_command_failed;
77 static volatile unsigned char sjcd_completion_status = 0;
78 static volatile unsigned char sjcd_completion_error = 0;
79 static unsigned short sjcd_command_is_in_progress = 0;
80 static unsigned short sjcd_error_reported = 0;
81
82 static int sjcd_open_count;
83
84 static int sjcd_audio_status;
85 static struct sjcd_play_msf sjcd_playing;
86
87 static short sjcd_port = SJCD_BASE_ADDR;
88 static int sjcd_irq = SJCD_INTR_NR;
89
90 static struct wait_queue *sjcd_waitq = NULL;
91
92
93
94
95 static volatile unsigned short sjcd_transfer_is_active = 0;
96
97 enum sjcd_transfer_state {
98 SJCD_S_IDLE = 0,
99 SJCD_S_START = 1,
100 SJCD_S_MODE = 2,
101 SJCD_S_READ = 3,
102 SJCD_S_DATA = 4,
103 SJCD_S_STOP = 5,
104 SJCD_S_STOPPING = 6
105 };
106 static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
107 static long sjcd_transfer_timeout = 0;
108 static int sjcd_read_count = 0;
109 #if 0
110 static unsigned short sjcd_tries;
111 #endif
112 static unsigned char sjcd_mode = 0;
113
114 #define SJCD_READ_TIMEOUT 5000
115
116
117
118
119 static struct sjcd_stat statistic;
120
121
122
123
124 static struct timer_list sjcd_delay_timer = { NULL, NULL, 0, 0, NULL };
125
126 #define SJCD_SET_TIMER( func, jiffies ) \
127 ( sjcd_delay_timer.expires = jiffies, \
128 sjcd_delay_timer.function = ( void * )func, \
129 add_timer( &sjcd_delay_timer ) )
130
131 #define CLEAR_TIMER del_timer( &sjcd_delay_timer )
132
133
134
135
136 void sjcd_setup( char *str, int *ints ){
137 printk( "Sanyo CDR-H94A device driver setup is called (%s).\n", str );
138 }
139
140
141
142
143 static unsigned char bin2bcd( int bin ){
144 int u, v;
145
146 u = bin % 10; v = bin / 10;
147 return( u | ( v << 4 ) );
148 }
149
150 static int bcd2bin( unsigned char bcd ){
151 return( ( bcd >> 4 ) * 10 + ( bcd & 0x0F ) );
152 }
153
154 static long msf2hsg( struct msf *mp ){
155 return( bcd2bin( mp->frame ) + bcd2bin( mp->sec ) * 75
156 + bcd2bin( mp->min ) * 4500 - 150 );
157 }
158
159 static void hsg2msf( long hsg, struct msf *msf ){
160 hsg += 150; msf->min = hsg / 4500;
161 hsg %= 4500; msf->sec = hsg / 75; msf->frame = hsg % 75;
162 msf->min = bin2bcd( msf->min );
163 msf->sec = bin2bcd( msf->sec );
164 msf->frame = bin2bcd( msf->frame );
165 }
166
167
168
169
170 static void sjcd_send_cmd( unsigned char cmd ){
171 #if 0
172 printk( "sjcd: send_cmd( 0x%x )\n", cmd );
173 #endif
174 outb( cmd, SJCDPORT( 0 ) );
175 sjcd_command_is_in_progress = 1;
176 sjcd_status_valid = 0;
177 sjcd_command_failed = 0;
178 }
179
180
181
182
183 static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){
184 #if 0
185 printk( "sjcd: send_1_cmd( 0x%x, 0x%x )\n", cmd, a );
186 #endif
187 outb( cmd, SJCDPORT( 0 ) );
188 outb( a, SJCDPORT( 0 ) );
189 sjcd_command_is_in_progress = 1;
190 sjcd_status_valid = 0;
191 sjcd_command_failed = 0;
192 }
193
194
195
196
197 static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a,
198 unsigned char b, unsigned char c, unsigned char d ){
199 #if 0
200 printk( "sjcd: send_4_cmd( 0x%x )\n", cmd );
201 #endif
202 outb( cmd, SJCDPORT( 0 ) );
203 outb( a, SJCDPORT( 0 ) );
204 outb( b, SJCDPORT( 0 ) );
205 outb( c, SJCDPORT( 0 ) );
206 outb( d, SJCDPORT( 0 ) );
207 sjcd_command_is_in_progress = 1;
208 sjcd_status_valid = 0;
209 sjcd_command_failed = 0;
210 }
211
212
213
214
215 static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){
216 #if 0
217 printk( "sjcd: send_long_cmd( 0x%x )\n", cmd );
218 #endif
219 outb( cmd, SJCDPORT( 0 ) );
220 outb( pms->start.min, SJCDPORT( 0 ) );
221 outb( pms->start.sec, SJCDPORT( 0 ) );
222 outb( pms->start.frame, SJCDPORT( 0 ) );
223 outb( pms->end.min, SJCDPORT( 0 ) );
224 outb( pms->end.sec, SJCDPORT( 0 ) );
225 outb( pms->end.frame, SJCDPORT( 0 ) );
226 sjcd_command_is_in_progress = 1;
227 sjcd_status_valid = 0;
228 sjcd_command_failed = 0;
229 }
230
231
232
233
234
235 static int sjcd_load_response( void *buf, int len ){
236 unsigned char *resp = ( unsigned char * )buf;
237
238 for( ; len; --len ){
239 int i;
240 for( i = 200; i-- && inb( SJCDPORT( 1 ) ) != 0x09; );
241 if( i > 0 ) *resp++ = ( unsigned char )inb( SJCDPORT( 0 ) );
242 else break;
243 }
244 return( len );
245 }
246
247
248
249
250 static void sjcd_load_status( void ){
251 sjcd_media_is_changed = 0;
252 sjcd_completion_error = 0;
253 sjcd_completion_status = inb( SJCDPORT( 0 ) );
254 if( sjcd_completion_status & SST_DOOR_OPENED ){
255 sjcd_door_closed = sjcd_media_is_available = 0;
256 } else {
257 sjcd_door_closed = 1;
258 if( sjcd_completion_status & SST_MEDIA_CHANGED )
259 sjcd_media_is_available = sjcd_media_is_changed = 1;
260 else if( sjcd_completion_status & 0x0F ){
261 while( ( inb( SJCDPORT( 1 ) ) & 0x0B ) != 0x09 );
262 sjcd_completion_error = inb( SJCDPORT( 0 ) );
263 if( ( sjcd_completion_status & 0x08 ) &&
264 ( sjcd_completion_error & 0x40 ) )
265 sjcd_media_is_available = 0;
266 else sjcd_command_failed = 1;
267 } else sjcd_media_is_available = 1;
268 }
269
270
271
272 sjcd_status_valid = 1, sjcd_error_reported = 0;
273 sjcd_command_is_in_progress = 0;
274 if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0;
275 #if 0
276 printk( "sjcd: status %02x.%02x loaded.\n",
277 ( int )sjcd_completion_status, ( int )sjcd_completion_error );
278 #endif
279 }
280
281
282
283
284 static int sjcd_check_status( void ){
285
286
287
288 if( ( inb( SJCDPORT( 1 ) ) & 0x0B ) == 0x09 ){
289 sjcd_load_status();
290 return( 1 );
291 } else {
292
293
294
295 return( 0 );
296 }
297 }
298
299 static volatile long sjcd_status_timeout;
300 #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
301
302 static void sjcd_status_timer( void ){
303 if( sjcd_check_status() ){
304 wake_up( &sjcd_waitq );
305 } else if( --sjcd_status_timeout <= 0 ){
306 wake_up( &sjcd_waitq );
307 } else {
308 SJCD_SET_TIMER( sjcd_status_timer, 1 );
309 }
310 }
311
312 static int sjcd_wait_for_status( void ){
313 sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
314 SJCD_SET_TIMER( sjcd_status_timer, 1 );
315 sleep_on( &sjcd_waitq );
316 if( sjcd_status_timeout <= 0 )
317 printk( "sjcd: Error Wait For Status.\n" );
318 return( sjcd_status_timeout );
319 }
320
321 static int sjcd_receive_status( void ){
322 int i;
323 #if 0
324 printk( "sjcd: receive_status\n" );
325 #endif
326
327
328
329 for( i = 200; i-- && ( sjcd_check_status() == 0 ); );
330 if( i < 0 ){
331 #if 0
332 printk( "sjcd: long wait for status\n" );
333 #endif
334 if( sjcd_wait_for_status() <= 0 )
335 printk( "sjcd: Timeout when read status.\n" );
336 else i = 0;
337 }
338 return( i );
339 }
340
341
342
343
344 static void sjcd_get_status( void ){
345 #if 0
346 printk( "sjcd: get_status\n" );
347 #endif
348 sjcd_send_cmd( SCMD_GET_STATUS );
349 sjcd_receive_status();
350 }
351
352
353
354
355 static int sjcd_disk_change( dev_t full_dev ){
356 #if 0
357 printk( "sjcd_disk_change( 0x%x )\n", full_dev );
358 #endif
359 if( MINOR( full_dev ) > 0 ){
360 printk( "sjcd: request error: invalid device minor.\n" );
361 return 0;
362 }
363 if( !sjcd_command_is_in_progress )
364 sjcd_get_status();
365 return( sjcd_status_valid ? sjcd_media_is_changed : 0 );
366 }
367
368
369
370
371
372 static struct sjcd_hw_disk_info sjcd_table_of_contents[ 100 ];
373 static unsigned char sjcd_first_track_no, sjcd_last_track_no;
374 #define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf
375
376 static int sjcd_update_toc( void ){
377 struct sjcd_hw_disk_info info;
378 int i;
379 #if 0
380 printk( "sjcd: update toc:\n" );
381 #endif
382
383
384
385 if( sjcd_toc_uptodate ) return( 0 );
386
387
388
389
390 sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK );
391 sjcd_receive_status();
392
393 if( !sjcd_status_valid ){
394 printk( "cannot load status.\n" );
395 return( -1 );
396 }
397
398 if( !sjcd_media_is_available ){
399 printk( "no disk in drive\n" );
400 return( -1 );
401 }
402
403 if( !sjcd_command_failed ){
404 if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
405 printk( "cannot load response about TOC start.\n" );
406 return( -1 );
407 }
408 sjcd_first_track_no = bcd2bin( info.un.track_no );
409 } else {
410 printk( "get first failed\n" );
411 return( -1 );
412 }
413 #if 0
414 printk( "TOC start 0x%02x ", sjcd_first_track_no );
415 #endif
416
417
418
419 sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK );
420 sjcd_receive_status();
421
422 if( !sjcd_status_valid ){
423 printk( "cannot load status.\n" );
424 return( -1 );
425 }
426
427 if( !sjcd_media_is_available ){
428 printk( "no disk in drive\n" );
429 return( -1 );
430 }
431
432 if( !sjcd_command_failed ){
433 if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
434 printk( "cannot load response about TOC finish.\n" );
435 return( -1 );
436 }
437 sjcd_last_track_no = bcd2bin( info.un.track_no );
438 } else {
439 printk( "get last failed\n" );
440 return( -1 );
441 }
442 #if 0
443 printk( "TOC finish 0x%02x ", sjcd_last_track_no );
444 #endif
445 for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){
446
447
448
449 sjcd_send_1_cmd( SCMD_GET_DISK_INFO, bin2bcd( i ) );
450 sjcd_receive_status();
451
452 if( !sjcd_status_valid ){
453 printk( "cannot load status.\n" );
454 return( -1 );
455 }
456
457 if( !sjcd_media_is_available ){
458 printk( "no disk in drive\n" );
459 return( -1 );
460 }
461
462 if( !sjcd_command_failed ){
463 if( sjcd_load_response( &sjcd_table_of_contents[ i ],
464 sizeof( struct sjcd_hw_disk_info ) ) != 0 ){
465 printk( "cannot load info for %d track\n", i );
466 return( -1 );
467 }
468 } else {
469 printk( "get info %d failed\n", i );
470 return( -1 );
471 }
472 }
473
474
475
476
477 sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE );
478 sjcd_receive_status();
479
480 if( !sjcd_status_valid ){
481 printk( "cannot load status.\n" );
482 return( -1 );
483 }
484
485 if( !sjcd_media_is_available ){
486 printk( "no disk in drive\n" );
487 return( -1 );
488 }
489
490 if( !sjcd_command_failed ){
491 if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
492 printk( "cannot load response about disk size.\n" );
493 return( -1 );
494 }
495 sjcd_disk_length.min = info.un.track_msf.min;
496 sjcd_disk_length.sec = info.un.track_msf.sec;
497 sjcd_disk_length.frame = info.un.track_msf.frame;
498 } else {
499 printk( "get size failed\n" );
500 return( 1 );
501 }
502 #if 0
503 printk( "(%02x:%02x.%02x)\n", sjcd_disk_length.min,
504 sjcd_disk_length.sec, sjcd_disk_length.frame );
505 #endif
506 return( 0 );
507 }
508
509
510
511
512 static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){
513 int s;
514 #if 0
515 printk( "sjcd: load sub q\n" );
516 #endif
517 sjcd_send_cmd( SCMD_GET_QINFO );
518 s = sjcd_receive_status();
519 if( s < 0 || sjcd_command_failed || !sjcd_status_valid ){
520 sjcd_send_cmd( 0xF2 );
521 s = sjcd_receive_status();
522 if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 );
523 sjcd_send_cmd( SCMD_GET_QINFO );
524 s = sjcd_receive_status();
525 if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 );
526 }
527 if( sjcd_media_is_available )
528 if( sjcd_load_response( qp, sizeof( *qp ) ) == 0 ) return( 0 );
529 return( -1 );
530 }
531
532
533
534
535 static int sjcd_play( struct sjcd_play_msf *mp ){
536 struct sjcd_play_msf msf;
537
538
539
540
541 sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_PLAY );
542 if( sjcd_receive_status() < 0 ) return( -1 );
543
544
545
546
547 msf.start = mp->start;
548 msf.end.min = msf.end.sec = msf.end.frame = 0x00;
549 sjcd_send_6_cmd( SCMD_SEEK, &msf );
550 if( sjcd_receive_status() < 0 ) return( -1 );
551
552
553
554
555 sjcd_send_6_cmd( SCMD_PLAY, mp );
556 return( sjcd_receive_status() );
557 }
558
559
560
561
562 static int sjcd_ioctl( struct inode *ip, struct file *fp,
563 unsigned int cmd, unsigned long arg ){
564 #if 0
565 printk( "sjcd:ioctl\n" );
566 #endif
567
568 if( ip == NULL ) return( -EINVAL );
569
570 sjcd_get_status();
571 if( !sjcd_status_valid ) return( -EIO );
572 if( sjcd_update_toc() < 0 ) return( -EIO );
573
574 switch( cmd ){
575 case CDROMSTART:{
576 #if 0
577 printk( "sjcd: ioctl: start\n" );
578 #endif
579 return( 0 );
580 }
581
582 case CDROMSTOP:{
583 #if 0
584 printk( "sjcd: ioctl: stop\n" );
585 #endif
586 sjcd_send_cmd( SCMD_PAUSE );
587 ( void )sjcd_receive_status();
588 sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
589 return( 0 );
590 }
591
592 case CDROMPAUSE:{
593 struct sjcd_hw_qinfo q_info;
594 #if 0
595 printk( "sjcd: ioctl: pause\n" );
596 #endif
597 if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
598 sjcd_send_cmd( SCMD_PAUSE );
599 ( void )sjcd_receive_status();
600 if( sjcd_get_q_info( &q_info ) < 0 ){
601 sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
602 } else {
603 sjcd_audio_status = CDROM_AUDIO_PAUSED;
604 sjcd_playing.start = q_info.abs;
605 }
606 return( 0 );
607 } else return( -EINVAL );
608 }
609
610 case CDROMRESUME:{
611 #if 0
612 printk( "sjcd: ioctl: resume\n" );
613 #endif
614 if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){
615
616
617
618 if( sjcd_play( &sjcd_playing ) < 0 ){
619 sjcd_audio_status = CDROM_AUDIO_ERROR;
620 return( -EIO );
621 } else {
622 sjcd_audio_status = CDROM_AUDIO_PLAY;
623 return( 0 );
624 }
625 } else return( -EINVAL );
626 }
627
628 case CDROMPLAYTRKIND:{
629 struct cdrom_ti ti; int s;
630 #if 0
631 printk( "sjcd: ioctl: playtrkind\n" );
632 #endif
633 if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( ti ) ) ) == 0 ){
634 memcpy_fromfs( &ti, (void *) arg, sizeof( ti ) );
635
636 if( ti.cdti_trk0 < sjcd_first_track_no ) return( -EINVAL );
637 if( ti.cdti_trk1 > sjcd_last_track_no )
638 ti.cdti_trk1 = sjcd_last_track_no;
639 if( ti.cdti_trk0 > ti.cdti_trk1 ) return( -EINVAL );
640
641 sjcd_playing.start = sjcd_table_of_contents[ ti.cdti_trk0 ].un.track_msf;
642 sjcd_playing.end = ( ti.cdti_trk1 < sjcd_last_track_no ) ?
643 sjcd_table_of_contents[ ti.cdti_trk1 + 1 ].un.track_msf :
644 sjcd_table_of_contents[ 0 ].un.track_msf;
645
646 if( sjcd_play( &sjcd_playing ) < 0 ){
647 sjcd_audio_status = CDROM_AUDIO_ERROR;
648 return( -EIO );
649 } else sjcd_audio_status = CDROM_AUDIO_PLAY;
650 }
651 return( s );
652 }
653
654 case CDROMPLAYMSF:{
655 struct cdrom_msf sjcd_msf; int s;
656 #if 0
657 printk( "sjcd: ioctl: playmsf\n" );
658 #endif
659 if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( sjcd_msf ) ) ) == 0 ){
660 if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
661 sjcd_send_cmd( SCMD_PAUSE );
662 ( void )sjcd_receive_status();
663 sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
664 }
665
666 memcpy_fromfs( &sjcd_msf, ( void * )arg, sizeof( sjcd_msf ) );
667
668 sjcd_playing.start.min = bin2bcd( sjcd_msf.cdmsf_min0 );
669 sjcd_playing.start.sec = bin2bcd( sjcd_msf.cdmsf_sec0 );
670 sjcd_playing.start.frame = bin2bcd( sjcd_msf.cdmsf_frame0 );
671 sjcd_playing.end.min = bin2bcd( sjcd_msf.cdmsf_min1 );
672 sjcd_playing.end.sec = bin2bcd( sjcd_msf.cdmsf_sec1 );
673 sjcd_playing.end.frame = bin2bcd( sjcd_msf.cdmsf_frame1 );
674
675 if( sjcd_play( &sjcd_playing ) < 0 ){
676 sjcd_audio_status = CDROM_AUDIO_ERROR;
677 return( -EIO );
678 } else sjcd_audio_status = CDROM_AUDIO_PLAY;
679 }
680 return( s );
681 }
682
683 case CDROMREADTOCHDR:{
684 struct cdrom_tochdr toc_header; int s;
685 #if 0
686 printk( "sjcd: ioctl: readtocheader\n" );
687 #endif
688 if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( toc_header ) ) ) == 0 ){
689 toc_header.cdth_trk0 = sjcd_first_track_no;
690 toc_header.cdth_trk1 = sjcd_last_track_no;
691 memcpy_tofs( ( void * )arg, &toc_header, sizeof( toc_header ) );
692 }
693 return( s );
694 }
695
696 case CDROMREADTOCENTRY:{
697 struct cdrom_tocentry toc_entry; int s;
698 #if 0
699 printk( "sjcd: ioctl: readtocentry\n" );
700 #endif
701 if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( toc_entry ) ) ) == 0 ){
702 struct sjcd_hw_disk_info *tp;
703
704 memcpy_fromfs( &toc_entry, ( void * )arg, sizeof( toc_entry ) );
705
706 if( toc_entry.cdte_track == CDROM_LEADOUT )
707 tp = &sjcd_table_of_contents[ 0 ];
708 else if( toc_entry.cdte_track < sjcd_first_track_no ) return( -EINVAL );
709 else if( toc_entry.cdte_track > sjcd_last_track_no ) return( -EINVAL );
710 else tp = &sjcd_table_of_contents[ toc_entry.cdte_track ];
711
712 toc_entry.cdte_adr = tp->track_control & 0x0F;
713 toc_entry.cdte_ctrl = tp->track_control >> 4;
714
715 switch( toc_entry.cdte_format ){
716 case CDROM_LBA:
717 toc_entry.cdte_addr.lba = msf2hsg( &( tp->un.track_msf ) );
718 break;
719 case CDROM_MSF:
720 toc_entry.cdte_addr.msf.minute = bcd2bin( tp->un.track_msf.min );
721 toc_entry.cdte_addr.msf.second = bcd2bin( tp->un.track_msf.sec );
722 toc_entry.cdte_addr.msf.frame = bcd2bin( tp->un.track_msf.frame );
723 break;
724 default: return( -EINVAL );
725 }
726 memcpy_tofs( ( void * )arg, &toc_entry, sizeof( toc_entry ) );
727 }
728 return( s );
729 }
730
731 case CDROMSUBCHNL:{
732 struct cdrom_subchnl subchnl; int s;
733 #if 0
734 printk( "sjcd: ioctl: subchnl\n" );
735 #endif
736 if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( subchnl ) ) ) == 0 ){
737 struct sjcd_hw_qinfo q_info;
738
739 memcpy_fromfs( &subchnl, ( void * )arg, sizeof( subchnl ) );
740 if( sjcd_get_q_info( &q_info ) < 0 ) return( -EIO );
741
742 subchnl.cdsc_audiostatus = sjcd_audio_status;
743 subchnl.cdsc_adr = q_info.track_control & 0x0F;
744 subchnl.cdsc_ctrl = q_info.track_control >> 4;
745 subchnl.cdsc_trk = bcd2bin( q_info.track_no );
746 subchnl.cdsc_ind = bcd2bin( q_info.x );
747
748 switch( subchnl.cdsc_format ){
749 case CDROM_LBA:
750 subchnl.cdsc_absaddr.lba = msf2hsg( &( q_info.abs ) );
751 subchnl.cdsc_reladdr.lba = msf2hsg( &( q_info.rel ) );
752 break;
753 case CDROM_MSF:
754 subchnl.cdsc_absaddr.msf.minute = bcd2bin( q_info.abs.min );
755 subchnl.cdsc_absaddr.msf.second = bcd2bin( q_info.abs.sec );
756 subchnl.cdsc_absaddr.msf.frame = bcd2bin( q_info.abs.frame );
757 subchnl.cdsc_reladdr.msf.minute = bcd2bin( q_info.rel.min );
758 subchnl.cdsc_reladdr.msf.second = bcd2bin( q_info.rel.sec );
759 subchnl.cdsc_reladdr.msf.frame = bcd2bin( q_info.rel.frame );
760 break;
761 default: return( -EINVAL );
762 }
763 memcpy_tofs( ( void * )arg, &subchnl, sizeof( subchnl ) );
764 }
765 return( s );
766 }
767
768 case CDROMVOLCTRL:{
769 struct cdrom_volctrl vol_ctrl; int s;
770 #if 0
771 printk( "sjcd: ioctl: volctrl\n" );
772 #endif
773 if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( vol_ctrl ) ) ) == 0 ){
774 unsigned char dummy[ 4 ];
775
776 memcpy_fromfs( &vol_ctrl, ( void * )arg, sizeof( vol_ctrl ) );
777 sjcd_send_4_cmd( SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF,
778 vol_ctrl.channel1, 0xFF );
779 if( sjcd_receive_status() < 0 ) return( -EIO );
780 ( void )sjcd_load_response( dummy, 4 );
781 }
782 return( s );
783 }
784
785 case CDROMEJECT:{
786 #if 0
787 printk( "sjcd: ioctl: eject\n" );
788 #endif
789 if( !sjcd_command_is_in_progress ){
790 sjcd_send_cmd( SCMD_EJECT_TRAY );
791 ( void )sjcd_receive_status();
792 }
793 return( 0 );
794 }
795
796 case 0xABCD:{
797 int s;
798 #if 0
799 printk( "sjcd: ioctl: statistic\n" );
800 #endif
801 if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( statistic ) ) ) == 0 )
802 memcpy_tofs( ( void * )arg, &statistic, sizeof( statistic ) );
803 return( s );
804 }
805
806 default:
807 return( -EINVAL );
808 }
809 }
810
811 #if 0
812
813
814
815
816 static void sjcd_interrupt( int irq, struct pt_regs *regs ){
817 printk( "sjcd: interrupt is cought\n" );
818 }
819 #endif
820
821
822
823
824 static void sjcd_invalidate_buffers( void ){
825 int i;
826 for( i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[ i++ ] = -1 );
827 sjcd_buf_out = -1;
828 }
829
830
831
832
833
834
835 #define CURRENT_IS_VALID \
836 ( CURRENT != NULL && MAJOR( CURRENT->dev ) == MAJOR_NR && \
837 CURRENT->cmd == READ && CURRENT->sector != -1 )
838
839 static void sjcd_transfer( void ){
840 #if 0
841 printk( "sjcd: transfer:\n" );
842 #endif
843 if( CURRENT_IS_VALID ){
844 while( CURRENT->nr_sectors ){
845 int i, bn = CURRENT->sector / 4;
846 for( i = 0; i < SJCD_BUF_SIZ && sjcd_buf_bn[ i ] != bn; i++ );
847 if( i < SJCD_BUF_SIZ ){
848 int offs = ( i * 4 + ( CURRENT->sector & 3 ) ) * 512;
849 int nr_sectors = 4 - ( CURRENT->sector & 3 );
850 if( sjcd_buf_out != i ){
851 sjcd_buf_out = i;
852 if( sjcd_buf_bn[ i ] != bn ){
853 sjcd_buf_out = -1;
854 continue;
855 }
856 }
857 if( nr_sectors > CURRENT->nr_sectors )
858 nr_sectors = CURRENT->nr_sectors;
859 #if 0
860 printk( "copy out\n" );
861 #endif
862 memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 );
863 CURRENT->nr_sectors -= nr_sectors;
864 CURRENT->sector += nr_sectors;
865 CURRENT->buffer += nr_sectors * 512;
866 } else {
867 sjcd_buf_out = -1;
868 break;
869 }
870 }
871 }
872 #if 0
873 printk( "sjcd: transfer: done\n" );
874 #endif
875 }
876
877 static void sjcd_poll( void ){
878
879
880
881 statistic.ticks++;
882 statistic.tticks[ sjcd_transfer_state ]++;
883
884 ReSwitch: switch( sjcd_transfer_state ){
885
886 case SJCD_S_IDLE:{
887 statistic.idle_ticks++;
888 #if 0
889 printk( "SJCD_S_IDLE\n" );
890 #endif
891 return;
892 }
893
894 case SJCD_S_START:{
895 statistic.start_ticks++;
896 sjcd_send_cmd( SCMD_GET_STATUS );
897 sjcd_transfer_state =
898 sjcd_mode == SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
899 sjcd_transfer_timeout = 500;
900 #if 0
901 printk( "SJCD_S_START: goto SJCD_S_%s mode\n",
902 sjcd_transfer_state == SJCD_S_READ ? "READ" : "MODE" );
903 #endif
904 break;
905 }
906
907 case SJCD_S_MODE:{
908 if( sjcd_check_status() ){
909
910
911
912 if( !sjcd_status_valid || sjcd_command_failed ){
913 #if 0
914 printk( "SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
915 #endif
916 sjcd_transfer_state = SJCD_S_STOP;
917 goto ReSwitch;
918 }
919
920 sjcd_mode = 0;
921 sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_COOKED );
922 sjcd_transfer_state = SJCD_S_READ; sjcd_transfer_timeout = 1000;
923 #if 0
924 printk( "SJCD_S_MODE: goto SJCD_S_READ mode\n" );
925 #endif
926 } else statistic.mode_ticks++;
927 break;
928 }
929
930 case SJCD_S_READ:{
931 if( sjcd_status_valid ? 1 : sjcd_check_status() ){
932
933
934
935 if( !sjcd_status_valid || sjcd_command_failed ){
936 #if 0
937 printk( "SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
938 #endif
939 sjcd_transfer_state = SJCD_S_STOP;
940 goto ReSwitch;
941 }
942 if( !sjcd_media_is_available ){
943 #if 0
944 printk( "SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n" );
945 #endif
946 sjcd_transfer_state = SJCD_S_STOP;
947 goto ReSwitch;
948 }
949 if( sjcd_mode != SCMD_MODE_COOKED ){
950
951
952
953 if( sjcd_load_response( &sjcd_mode, 1 ) != 0 ){
954 #if 0
955 printk( "SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n" );
956 #endif
957 sjcd_transfer_state = SJCD_S_STOP;
958 goto ReSwitch;
959 }
960 if( sjcd_mode != SCMD_MODE_COOKED ){
961 #if 0
962 printk( "SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n" );
963 #endif
964 sjcd_transfer_state = SJCD_S_STOP;
965 goto ReSwitch;
966 }
967 }
968
969 if( CURRENT_IS_VALID ){
970 struct sjcd_play_msf msf;
971
972 sjcd_next_bn = CURRENT->sector / 4;
973 hsg2msf( sjcd_next_bn, &msf.start );
974 msf.end.min = 0; msf.end.sec = 0;
975 msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ;
976 #if 0
977 printk( "---reading msf-address %x:%x:%x %x:%x:%x\n",
978 msf.start.min, msf.start.sec, msf.start.frame,
979 msf.end.min, msf.end.sec, msf.end.frame );
980 printk( "sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", \
981 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
982 sjcd_buf_bn[ sjcd_buf_in ] );
983 #endif
984 sjcd_send_6_cmd( SCMD_DATA_READ, &msf );
985 sjcd_transfer_state = SJCD_S_DATA;
986 sjcd_transfer_timeout = 500;
987 #if 0
988 printk( "SJCD_S_READ: go to SJCD_S_DATA mode\n" );
989 #endif
990 } else {
991 #if 0
992 printk( "SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n" );
993 #endif
994 sjcd_transfer_state = SJCD_S_STOP;
995 goto ReSwitch;
996 }
997 } else statistic.read_ticks++;
998 break;
999 }
1000
1001 case SJCD_S_DATA:{
1002 unsigned char stat;
1003
1004 sjcd_s_data: stat = inb( SJCDPORT( 1 ) ) & 0x0B;
1005 #if 0
1006 printk( "SJCD_S_DATA: status = 0x%02x\n", stat );
1007 #endif
1008 if( stat == 0x09 ){
1009
1010
1011
1012
1013 sjcd_load_status();
1014
1015 if( !sjcd_status_valid || sjcd_command_failed ){
1016 printk( "sjcd: read block %d failed, maybe audio disk? Giving up\n",
1017 sjcd_next_bn );
1018 if( CURRENT_IS_VALID ) end_request( 0 );
1019 printk( "SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n" );
1020 sjcd_transfer_state = SJCD_S_STOP;
1021 goto ReSwitch;
1022 }
1023
1024 if( !sjcd_media_is_available ){
1025 printk( "SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n" );
1026 sjcd_transfer_state = SJCD_S_STOP;
1027 goto ReSwitch;
1028 }
1029
1030 sjcd_transfer_state = SJCD_S_START;
1031 goto ReSwitch;
1032 } else if( stat == 0x0A ){
1033
1034
1035
1036
1037
1038 if( !CURRENT_IS_VALID && sjcd_buf_in == sjcd_buf_out ){
1039 printk( "SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n" );
1040 printk( " ... all the date would be discarded\n" );
1041 sjcd_transfer_state = SJCD_S_STOP;
1042 goto ReSwitch;
1043 }
1044
1045
1046
1047
1048
1049 sjcd_buf_bn[ sjcd_buf_in ] = -1;
1050 insb( SJCDPORT( 2 ), sjcd_buf + 2048 * sjcd_buf_in, 2048 );
1051 #if 0
1052 printk( "SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
1053 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
1054 sjcd_buf_bn[ sjcd_buf_in ] );
1055 #endif
1056 sjcd_buf_bn[ sjcd_buf_in ] = sjcd_next_bn++;
1057 if( sjcd_buf_out == -1 ) sjcd_buf_out = sjcd_buf_in;
1058 if( ++sjcd_buf_in == SJCD_BUF_SIZ ) sjcd_buf_in = 0;
1059
1060
1061
1062
1063
1064 if( --sjcd_read_count == 0 ){
1065
1066
1067
1068 if( !sjcd_transfer_is_active ){
1069 while( CURRENT_IS_VALID ){
1070
1071
1072
1073 sjcd_transfer();
1074 if( CURRENT->nr_sectors == 0 ) end_request( 1 );
1075 else break;
1076 }
1077 }
1078 if( CURRENT_IS_VALID &&
1079 ( CURRENT->sector / 4 < sjcd_next_bn ||
1080 CURRENT->sector / 4 > sjcd_next_bn + SJCD_BUF_SIZ ) ){
1081 #if 0
1082 printk( "SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n" );
1083 #endif
1084 sjcd_transfer_state = SJCD_S_STOP;
1085 goto ReSwitch;
1086 }
1087 }
1088 goto sjcd_s_data;
1089
1090 } else statistic.data_ticks++;
1091 break;
1092 }
1093
1094 case SJCD_S_STOP:{
1095 sjcd_read_count = 0;
1096 sjcd_send_cmd( SCMD_STOP );
1097 sjcd_transfer_state = SJCD_S_STOPPING;
1098 sjcd_transfer_timeout = 500;
1099 statistic.stop_ticks++;
1100 break;
1101 }
1102
1103 case SJCD_S_STOPPING:{
1104 unsigned char stat;
1105
1106 stat = inb( SJCDPORT( 1 ) ) & 0x0B;
1107 #if 0
1108 printk( "SJCD_S_STOP: status = 0x%02x\n", stat );
1109 #endif
1110 if( stat == 0x0A ){
1111 int i;
1112 #if 0
1113 printk( "SJCD_S_STOP: discard data\n" );
1114 #endif
1115
1116
1117
1118 for( i = 2048; i--; ( void )inb( SJCDPORT( 2 ) ) );
1119 sjcd_transfer_timeout = 500;
1120 } else if( stat == 0x09 ){
1121 sjcd_load_status();
1122 if( sjcd_status_valid && sjcd_media_is_changed ) {
1123 sjcd_toc_uptodate = 0;
1124 sjcd_invalidate_buffers();
1125 }
1126 if( CURRENT_IS_VALID ){
1127 if( sjcd_status_valid ) sjcd_transfer_state = SJCD_S_READ;
1128 else sjcd_transfer_state = SJCD_S_START;
1129 } else sjcd_transfer_state = SJCD_S_IDLE;
1130 goto ReSwitch;
1131 } else statistic.stopping_ticks++;
1132 break;
1133 }
1134
1135 default:
1136 printk( "sjcd_poll: invalid state %d\n", sjcd_transfer_state );
1137 return;
1138 }
1139
1140 if( --sjcd_transfer_timeout == 0 ){
1141 printk( "sjcd: timeout in state %d\n", sjcd_transfer_state );
1142 while( CURRENT_IS_VALID ) end_request( 0 );
1143 sjcd_send_cmd( SCMD_STOP );
1144 sjcd_transfer_state = SJCD_S_IDLE;
1145 goto ReSwitch;
1146 }
1147
1148
1149
1150
1151 SJCD_SET_TIMER( sjcd_poll, 1 );
1152 }
1153
1154 static void do_sjcd_request( void ){
1155 #if 0
1156 printk( "sjcd: do_sjcd_request(%ld+%ld)\n",
1157 CURRENT->sector, CURRENT->nr_sectors );
1158 #endif
1159 sjcd_transfer_is_active = 1;
1160 while( CURRENT_IS_VALID ){
1161
1162
1163
1164 if( CURRENT->bh && !( CURRENT->bh->b_lock ) )
1165 panic( DEVICE_NAME ": block not locked" );
1166
1167 sjcd_transfer();
1168 if( CURRENT->nr_sectors == 0 ) end_request( 1 );
1169 else {
1170 sjcd_buf_out = -1;
1171 if( sjcd_transfer_state == SJCD_S_IDLE ){
1172 if( !sjcd_toc_uptodate ){
1173 if( sjcd_update_toc() < 0 ){
1174 printk( "sjcd: transfer: discard\n" );
1175 while( CURRENT_IS_VALID ) end_request( 0 );
1176 break;
1177 }
1178 }
1179 sjcd_transfer_state = SJCD_S_START;
1180 SJCD_SET_TIMER( sjcd_poll, 1 );
1181 }
1182 break;
1183 }
1184 }
1185 sjcd_transfer_is_active = 0;
1186 #if 0
1187 printk( "sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
1188 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[ sjcd_buf_in ] );
1189 printk( "do_sjcd_request ends\n" );
1190 #endif
1191 }
1192
1193
1194
1195
1196 int sjcd_open( struct inode *ip, struct file *fp ){
1197
1198
1199
1200 if( !sjcd_present ) return( -ENXIO );
1201
1202
1203
1204
1205 if( fp->f_mode & 2 ) return( -EROFS );
1206
1207 if( sjcd_open_count == 0 ){
1208 sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
1209 sjcd_mode = 0;
1210 sjcd_transfer_state = SJCD_S_IDLE;
1211 sjcd_invalidate_buffers();
1212
1213
1214
1215
1216 sjcd_get_status();
1217 if( !sjcd_status_valid ){
1218 #if 0
1219 printk( "sjcd: open: timed out when check status.\n" );
1220 #endif
1221 return( -EIO );
1222 } else if( !sjcd_media_is_available ){
1223 #if 0
1224 printk("sjcd: open: no disk in drive\n");
1225 #endif
1226 return( -EIO );
1227 }
1228 #if 0
1229 printk( "sjcd: open: done\n" );
1230 #endif
1231 }
1232 return( ++sjcd_open_count, 0 );
1233 }
1234
1235
1236
1237
1238 static void sjcd_release( struct inode *inode, struct file *file ){
1239 #if 0
1240 printk( "sjcd: release\n" );
1241 #endif
1242 if( --sjcd_open_count == 0 ){
1243 sjcd_invalidate_buffers();
1244 sync_dev( inode->i_rdev );
1245 invalidate_buffers( inode->i_rdev );
1246 }
1247 }
1248
1249
1250
1251
1252 static struct file_operations sjcd_fops = {
1253 NULL,
1254 block_read,
1255 block_write,
1256 NULL,
1257 NULL,
1258 sjcd_ioctl,
1259 NULL,
1260 sjcd_open,
1261 sjcd_release,
1262 NULL,
1263 NULL,
1264 sjcd_disk_change,
1265 NULL
1266 };
1267
1268
1269
1270
1271
1272
1273 static struct {
1274 unsigned char major, minor;
1275 } sjcd_version;
1276
1277
1278
1279
1280
1281 unsigned long sjcd_init( unsigned long mem_start, unsigned long mem_end ){
1282 int i;
1283
1284 if( sjcd_port != 0x340 || sjcd_irq != 0x0A ){
1285 printk( "skip sjcd_init\n" );
1286 return( mem_start );
1287 }
1288
1289 #ifdef CONFIG_ISP_16
1290
1291
1292
1293 isp16_cdi_setup( ISP_CDROM_SANYO, ISP_CDROM_IRQ_10,
1294 ISP_CDROM_DMA_DISABLED, ISP_CDROM_PORT_340 );
1295 #endif
1296
1297 #if 0
1298 printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq );
1299 #endif
1300
1301 if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
1302 printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
1303 return( mem_start );
1304 }
1305
1306 blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
1307 read_ahead[ MAJOR_NR ] = 4;
1308
1309 if( check_region( sjcd_port, 4 ) ){
1310 printk( "Init failed, I/O port (%X) is already in use\n",
1311 sjcd_port );
1312 return( mem_start );
1313 }
1314
1315 printk( "Sanyo CDR-H94A:" );
1316
1317
1318
1319
1320 for( i = 100; i > 0; --i )
1321 if( !( inb( SJCDPORT( 1 ) ) & 0x04 ) ) break;
1322 if( i == 0 ){
1323 printk( " No device at 0x%x found.\n", sjcd_port );
1324 return( mem_start );
1325 }
1326
1327 sjcd_send_cmd( SCMD_RESET );
1328 while( !sjcd_status_valid ) ( void )sjcd_check_status();
1329
1330
1331
1332
1333 sjcd_send_cmd( SCMD_GET_VERSION );
1334 while( !sjcd_status_valid ) ( void )sjcd_check_status();
1335
1336 if( sjcd_load_response( &sjcd_version, sizeof( sjcd_version ) ) == 0 ){
1337 printk( " Version %1x.%02x.", ( int )sjcd_version.major,
1338 ( int )sjcd_version.minor );
1339 } else {
1340 printk( " Read version failed.\n" );
1341 return( mem_start );
1342 }
1343
1344
1345
1346
1347 if( !sjcd_status_valid ){
1348 sjcd_send_cmd( SCMD_GET_STATUS );
1349 while( !sjcd_status_valid ) ( void )sjcd_check_status();
1350 }
1351
1352 printk( " Status: port=0x%x, irq=%d\n",
1353 sjcd_port, sjcd_irq );
1354
1355 sjcd_present++;
1356 return( mem_start );
1357 }
1358