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
- sjcd_cleanup
- init_module
- cleanup_module
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 #define SJCD_VERSION_MAJOR 1
52 #define SJCD_VERSION_MINOR 6
53
54 #ifdef MODULE
55 #include <linux/module.h>
56 #endif
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
80
81
82
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
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
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
136
137 static struct sjcd_stat statistic;
138 #endif
139
140
141
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
156
157
158 void sjcd_setup( char *str, int *ints )
159 {
160 if (ints[0] > 0)
161 sjcd_base = ints[1];
162 }
163
164
165
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 );
187 msf->sec = bin2bcd( msf->sec );
188 msf->frame = bin2bcd( msf->frame );
189 }
190
191
192
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
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
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
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
257
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
273
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
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
299
300 sjcd_status_valid = 1, sjcd_error_reported = 0;
301 sjcd_command_is_in_progress = 0;
302
303
304
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
315
316 static int sjcd_check_status( void ){
317
318
319
320 if( SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ){
321 sjcd_load_status();
322 return( 1 );
323 } else {
324
325
326
327 return( 0 );
328 }
329 }
330
331
332
333
334 static volatile long sjcd_status_timeout;
335
336
337
338
339
340
341 #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
342
343 static void sjcd_status_timer( void ){
344 if( sjcd_check_status() ){
345
346
347
348 wake_up( &sjcd_waitq );
349 } else if( --sjcd_status_timeout <= 0 ){
350
351
352
353 wake_up( &sjcd_waitq );
354 } else {
355
356
357
358 SJCD_SET_TIMER( sjcd_status_timer, 1 );
359 }
360 }
361
362
363
364
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
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
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
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
426
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
440
441 if( sjcd_toc_uptodate ) return( 0 );
442
443
444
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
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
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
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
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
590
591 static int sjcd_play( struct sjcd_play_msf *mp ){
592 struct sjcd_play_msf msf;
593
594
595
596
597 sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_PLAY );
598 if( sjcd_receive_status() < 0 ) return( -1 );
599
600
601
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
610
611 sjcd_send_6_cmd( SCMD_PLAY, mp );
612 return( sjcd_receive_status() );
613 }
614
615
616
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
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
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
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
916
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
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
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;
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
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
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
1107
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
1135
1136
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
1149
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
1164
1165
1166 if( --sjcd_read_count == 0 ){
1167
1168
1169
1170 if( !sjcd_transfer_is_active ){
1171 while( CURRENT_IS_VALID ){
1172
1173
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
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
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
1262
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
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;
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
1308
1309 int sjcd_open( struct inode *ip, struct file *fp ){
1310
1311
1312
1313 if( !sjcd_present ) return( -ENXIO );
1314
1315
1316
1317
1318 if( fp->f_mode & 2 ) return( -EROFS );
1319
1320 if( sjcd_open_count == 0 ){
1321 int s, sjcd_open_tries;
1322
1323
1324
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
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
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
1416
1417 static struct file_operations sjcd_fops = {
1418 NULL,
1419 block_read,
1420 block_write,
1421 NULL,
1422 NULL,
1423 sjcd_ioctl,
1424 NULL,
1425 sjcd_open,
1426 sjcd_release,
1427 NULL,
1428 NULL,
1429 sjcd_disk_change,
1430 NULL
1431 };
1432
1433
1434
1435
1436
1437
1438
1439 static struct {
1440 unsigned char major, minor;
1441 } sjcd_version;
1442
1443
1444
1445
1446
1447 int sjcd_init( void ){
1448 int i;
1449
1450 printk("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
1474
1475
1476 printk( "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
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
1496
1497 printk( "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
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
1526
1527 if( !sjcd_status_valid ){
1528 printk( "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
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("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( "SJCD: module: removed.\n");
1577 }
1578 #endif