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