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