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/sched.h>
64#include <linux/mm.h>
65#include <linux/timer.h>
66#include <linux/fs.h>
67#include <linux/kernel.h>
68#include <linux/cdrom.h>
69#include <linux/ioport.h>
70#include <linux/string.h>
71#include <linux/major.h>
72#include <linux/init.h>
73#include <linux/devfs_fs_kernel.h>
74
75#include <asm/system.h>
76#include <asm/io.h>
77#include <asm/uaccess.h>
78
79#define MAJOR_NR SANYO_CDROM_MAJOR
80#include <linux/blk.h>
81#include "sjcd.h"
82
83static int sjcd_present = 0;
84
85#define SJCD_BUF_SIZ 32		/* cdr-h94a has internal 64K buffer */
86
87/*
88 * buffer for block size conversion
89 */
90static char sjcd_buf[2048 * SJCD_BUF_SIZ];
91static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
92static volatile int sjcd_buf_in, sjcd_buf_out = -1;
93
94/*
95 * Status.
96 */
97static unsigned short sjcd_status_valid = 0;
98static unsigned short sjcd_door_closed;
99static unsigned short sjcd_door_was_open;
100static unsigned short sjcd_media_is_available;
101static unsigned short sjcd_media_is_changed;
102static unsigned short sjcd_toc_uptodate = 0;
103static unsigned short sjcd_command_failed;
104static volatile unsigned char sjcd_completion_status = 0;
105static volatile unsigned char sjcd_completion_error = 0;
106static unsigned short sjcd_command_is_in_progress = 0;
107static unsigned short sjcd_error_reported = 0;
108
109static int sjcd_open_count;
110
111static int sjcd_audio_status;
112static struct sjcd_play_msf sjcd_playing;
113
114static int sjcd_base = SJCD_BASE_ADDR;
115
116MODULE_PARM(sjcd_base, "i");
117
118static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
119
120/*
121 * Data transfer.
122 */
123static volatile unsigned short sjcd_transfer_is_active = 0;
124
125enum sjcd_transfer_state {
126	SJCD_S_IDLE = 0,
127	SJCD_S_START = 1,
128	SJCD_S_MODE = 2,
129	SJCD_S_READ = 3,
130	SJCD_S_DATA = 4,
131	SJCD_S_STOP = 5,
132	SJCD_S_STOPPING = 6
133};
134static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
135static long sjcd_transfer_timeout = 0;
136static int sjcd_read_count = 0;
137static unsigned char sjcd_mode = 0;
138
139#define SJCD_READ_TIMEOUT 5000
140
141#if defined(SJCD_GATHER_STAT)
142/*
143 * Statistic.
144 */
145static struct sjcd_stat statistic;
146#endif
147
148/*
149 * Timer.
150 */
151static struct timer_list sjcd_delay_timer;
152
153#define SJCD_SET_TIMER( func, tmout )           \
154    ( sjcd_delay_timer.expires = jiffies+tmout,         \
155      sjcd_delay_timer.function = ( void * )func, \
156      add_timer( &sjcd_delay_timer ) )
157
158#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
159
160static int sjcd_cleanup(void);
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(kdev_t full_dev)
457{
458	if (MINOR(full_dev) > 0) {
459		printk("SJCD: request error: invalid device minor.\n");
460		return 0;
461	}
462	if (!sjcd_command_is_in_progress)
463		sjcd_get_status();
464	return (sjcd_status_valid ? sjcd_media_is_changed : 0);
465}
466
467/*
468 * Read the table of contents (TOC) and TOC header if necessary.
469 * We assume that the drive contains no more than 99 toc entries.
470 */
471static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
472static unsigned char sjcd_first_track_no, sjcd_last_track_no;
473#define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
474
475static int sjcd_update_toc(void)
476{
477	struct sjcd_hw_disk_info info;
478	int i;
479#if defined(SJCD_TRACE)
480	printk("SJCD: update toc:\n");
481#endif
482	/*
483	 * check to see if we need to do anything
484	 */
485	if (sjcd_toc_uptodate)
486		return (0);
487
488	/*
489	 * Get the TOC start information.
490	 */
491	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
492	sjcd_receive_status();
493
494	if (!sjcd_status_valid) {
495		printk("SJCD: cannot load status.\n");
496		return (-1);
497	}
498
499	if (!sjcd_media_is_available) {
500		printk("SJCD: no disk in drive\n");
501		return (-1);
502	}
503
504	if (!sjcd_command_failed) {
505		if (sjcd_load_response(&info, sizeof(info)) != 0) {
506			printk
507			    ("SJCD: cannot load response about TOC start.\n");
508			return (-1);
509		}
510		sjcd_first_track_no = bcd2bin(info.un.track_no);
511	} else {
512		printk("SJCD: get first failed\n");
513		return (-1);
514	}
515#if defined(SJCD_TRACE)
516	printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
517#endif
518	/*
519	 * Get the TOC finish information.
520	 */
521	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
522	sjcd_receive_status();
523
524	if (!sjcd_status_valid) {
525		printk("SJCD: cannot load status.\n");
526		return (-1);
527	}
528
529	if (!sjcd_media_is_available) {
530		printk("SJCD: no disk in drive\n");
531		return (-1);
532	}
533
534	if (!sjcd_command_failed) {
535		if (sjcd_load_response(&info, sizeof(info)) != 0) {
536			printk
537			    ("SJCD: cannot load response about TOC finish.\n");
538			return (-1);
539		}
540		sjcd_last_track_no = bcd2bin(info.un.track_no);
541	} else {
542		printk("SJCD: get last failed\n");
543		return (-1);
544	}
545#if defined(SJCD_TRACE)
546	printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
547#endif
548	for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
549		/*
550		 * Get the first track information.
551		 */
552		sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
553		sjcd_receive_status();
554
555		if (!sjcd_status_valid) {
556			printk("SJCD: cannot load status.\n");
557			return (-1);
558		}
559
560		if (!sjcd_media_is_available) {
561			printk("SJCD: no disk in drive\n");
562			return (-1);
563		}
564
565		if (!sjcd_command_failed) {
566			if (sjcd_load_response(&sjcd_table_of_contents[i],
567					       sizeof(struct
568						      sjcd_hw_disk_info))
569			    != 0) {
570				printk
571				    ("SJCD: cannot load info for %d track\n",
572				     i);
573				return (-1);
574			}
575		} else {
576			printk("SJCD: get info %d failed\n", i);
577			return (-1);
578		}
579	}
580
581	/*
582	 * Get the disk length info.
583	 */
584	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
585	sjcd_receive_status();
586
587	if (!sjcd_status_valid) {
588		printk("SJCD: cannot load status.\n");
589		return (-1);
590	}
591
592	if (!sjcd_media_is_available) {
593		printk("SJCD: no disk in drive\n");
594		return (-1);
595	}
596
597	if (!sjcd_command_failed) {
598		if (sjcd_load_response(&info, sizeof(info)) != 0) {
599			printk
600			    ("SJCD: cannot load response about disk size.\n");
601			return (-1);
602		}
603		sjcd_disk_length.min = info.un.track_msf.min;
604		sjcd_disk_length.sec = info.un.track_msf.sec;
605		sjcd_disk_length.frame = info.un.track_msf.frame;
606	} else {
607		printk("SJCD: get size failed\n");
608		return (1);
609	}
610#if defined(SJCD_TRACE)
611	printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
612	       sjcd_disk_length.sec, sjcd_disk_length.frame);
613#endif
614	return (0);
615}
616
617/*
618 * Load subchannel information.
619 */
620static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
621{
622	int s;
623#if defined(SJCD_TRACE)
624	printk("SJCD: load sub q\n");
625#endif
626	sjcd_send_cmd(SCMD_GET_QINFO);
627	s = sjcd_receive_status();
628	if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
629		sjcd_send_cmd(0xF2);
630		s = sjcd_receive_status();
631		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
632			return (-1);
633		sjcd_send_cmd(SCMD_GET_QINFO);
634		s = sjcd_receive_status();
635		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
636			return (-1);
637	}
638	if (sjcd_media_is_available)
639		if (sjcd_load_response(qp, sizeof(*qp)) == 0)
640			return (0);
641	return (-1);
642}
643
644/*
645 * Start playing from the specified position.
646 */
647static int sjcd_play(struct sjcd_play_msf *mp)
648{
649	struct sjcd_play_msf msf;
650
651	/*
652	 * Turn the device to play mode.
653	 */
654	sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
655	if (sjcd_receive_status() < 0)
656		return (-1);
657
658	/*
659	 * Seek to the starting point.
660	 */
661	msf.start = mp->start;
662	msf.end.min = msf.end.sec = msf.end.frame = 0x00;
663	sjcd_send_6_cmd(SCMD_SEEK, &msf);
664	if (sjcd_receive_status() < 0)
665		return (-1);
666
667	/*
668	 * Start playing.
669	 */
670	sjcd_send_6_cmd(SCMD_PLAY, mp);
671	return (sjcd_receive_status());
672}
673
674/*
675 * Tray control functions.
676 */
677static int sjcd_tray_close(void)
678{
679#if defined(SJCD_TRACE)
680	printk("SJCD: tray_close\n");
681#endif
682	sjcd_send_cmd(SCMD_CLOSE_TRAY);
683	return (sjcd_receive_status());
684}
685
686static int sjcd_tray_lock(void)
687{
688#if defined(SJCD_TRACE)
689	printk("SJCD: tray_lock\n");
690#endif
691	sjcd_send_cmd(SCMD_LOCK_TRAY);
692	return (sjcd_receive_status());
693}
694
695static int sjcd_tray_unlock(void)
696{
697#if defined(SJCD_TRACE)
698	printk("SJCD: tray_unlock\n");
699#endif
700	sjcd_send_cmd(SCMD_UNLOCK_TRAY);
701	return (sjcd_receive_status());
702}
703
704static int sjcd_tray_open(void)
705{
706#if defined(SJCD_TRACE)
707	printk("SJCD: tray_open\n");
708#endif
709	sjcd_send_cmd(SCMD_EJECT_TRAY);
710	return (sjcd_receive_status());
711}
712
713/*
714 * Do some user commands.
715 */
716static int sjcd_ioctl(struct inode *ip, struct file *fp,
717		      unsigned int cmd, unsigned long arg)
718{
719#if defined(SJCD_TRACE)
720	printk("SJCD:ioctl\n");
721#endif
722
723	if (ip == NULL)
724		return (-EINVAL);
725
726	sjcd_get_status();
727	if (!sjcd_status_valid)
728		return (-EIO);
729	if (sjcd_update_toc() < 0)
730		return (-EIO);
731
732	switch (cmd) {
733	case CDROMSTART:{
734#if defined(SJCD_TRACE)
735			printk("SJCD: ioctl: start\n");
736#endif
737			return (0);
738		}
739
740	case CDROMSTOP:{
741#if defined(SJCD_TRACE)
742			printk("SJCD: ioctl: stop\n");
743#endif
744			sjcd_send_cmd(SCMD_PAUSE);
745			(void) sjcd_receive_status();
746			sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
747			return (0);
748		}
749
750	case CDROMPAUSE:{
751			struct sjcd_hw_qinfo q_info;
752#if defined(SJCD_TRACE)
753			printk("SJCD: ioctl: pause\n");
754#endif
755			if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
756				sjcd_send_cmd(SCMD_PAUSE);
757				(void) sjcd_receive_status();
758				if (sjcd_get_q_info(&q_info) < 0) {
759					sjcd_audio_status =
760					    CDROM_AUDIO_NO_STATUS;
761				} else {
762					sjcd_audio_status =
763					    CDROM_AUDIO_PAUSED;
764					sjcd_playing.start = q_info.abs;
765				}
766				return (0);
767			} else
768				return (-EINVAL);
769		}
770
771	case CDROMRESUME:{
772#if defined(SJCD_TRACE)
773			printk("SJCD: ioctl: resume\n");
774#endif
775			if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
776				/*
777				 * continue play starting at saved location
778				 */
779				if (sjcd_play(&sjcd_playing) < 0) {
780					sjcd_audio_status =
781					    CDROM_AUDIO_ERROR;
782					return (-EIO);
783				} else {
784					sjcd_audio_status =
785					    CDROM_AUDIO_PLAY;
786					return (0);
787				}
788			} else
789				return (-EINVAL);
790		}
791
792	case CDROMPLAYTRKIND:{
793			struct cdrom_ti ti;
794			int s;
795#if defined(SJCD_TRACE)
796			printk("SJCD: ioctl: playtrkind\n");
797#endif
798			if ((s =
799			     verify_area(VERIFY_READ, (void *) arg,
800					 sizeof(ti))) == 0) {
801				copy_from_user(&ti, (void *) arg,
802					       sizeof(ti));
803
804				if (ti.cdti_trk0 < sjcd_first_track_no)
805					return (-EINVAL);
806				if (ti.cdti_trk1 > sjcd_last_track_no)
807					ti.cdti_trk1 = sjcd_last_track_no;
808				if (ti.cdti_trk0 > ti.cdti_trk1)
809					return (-EINVAL);
810
811				sjcd_playing.start =
812				    sjcd_table_of_contents[ti.cdti_trk0].
813				    un.track_msf;
814				sjcd_playing.end =
815				    (ti.cdti_trk1 <
816				     sjcd_last_track_no) ?
817				    sjcd_table_of_contents[ti.cdti_trk1 +
818							   1].un.
819				    track_msf : sjcd_table_of_contents[0].
820				    un.track_msf;
821
822				if (sjcd_play(&sjcd_playing) < 0) {
823					sjcd_audio_status =
824					    CDROM_AUDIO_ERROR;
825					return (-EIO);
826				} else
827					sjcd_audio_status =
828					    CDROM_AUDIO_PLAY;
829			}
830			return (s);
831		}
832
833	case CDROMPLAYMSF:{
834			struct cdrom_msf sjcd_msf;
835			int s;
836#if defined(SJCD_TRACE)
837			printk("SJCD: ioctl: playmsf\n");
838#endif
839			if ((s =
840			     verify_area(VERIFY_READ, (void *) arg,
841					 sizeof(sjcd_msf))) == 0) {
842				if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
843					sjcd_send_cmd(SCMD_PAUSE);
844					(void) sjcd_receive_status();
845					sjcd_audio_status =
846					    CDROM_AUDIO_NO_STATUS;
847				}
848
849				copy_from_user(&sjcd_msf, (void *) arg,
850					       sizeof(sjcd_msf));
851
852				sjcd_playing.start.min =
853				    bin2bcd(sjcd_msf.cdmsf_min0);
854				sjcd_playing.start.sec =
855				    bin2bcd(sjcd_msf.cdmsf_sec0);
856				sjcd_playing.start.frame =
857				    bin2bcd(sjcd_msf.cdmsf_frame0);
858				sjcd_playing.end.min =
859				    bin2bcd(sjcd_msf.cdmsf_min1);
860				sjcd_playing.end.sec =
861				    bin2bcd(sjcd_msf.cdmsf_sec1);
862				sjcd_playing.end.frame =
863				    bin2bcd(sjcd_msf.cdmsf_frame1);
864
865				if (sjcd_play(&sjcd_playing) < 0) {
866					sjcd_audio_status =
867					    CDROM_AUDIO_ERROR;
868					return (-EIO);
869				} else
870					sjcd_audio_status =
871					    CDROM_AUDIO_PLAY;
872			}
873			return (s);
874		}
875
876	case CDROMREADTOCHDR:{
877			struct cdrom_tochdr toc_header;
878			int s;
879#if defined(SJCD_TRACE)
880			printk("SJCD: ioctl: readtocheader\n");
881#endif
882			if ((s =
883			     verify_area(VERIFY_WRITE, (void *) arg,
884					 sizeof(toc_header))) == 0) {
885				toc_header.cdth_trk0 = sjcd_first_track_no;
886				toc_header.cdth_trk1 = sjcd_last_track_no;
887				copy_to_user((void *) arg, &toc_header,
888					     sizeof(toc_header));
889			}
890			return (s);
891		}
892
893	case CDROMREADTOCENTRY:{
894			struct cdrom_tocentry toc_entry;
895			int s;
896#if defined(SJCD_TRACE)
897			printk("SJCD: ioctl: readtocentry\n");
898#endif
899			if ((s =
900			     verify_area(VERIFY_WRITE, (void *) arg,
901					 sizeof(toc_entry))) == 0) {
902				struct sjcd_hw_disk_info *tp;
903
904				copy_from_user(&toc_entry, (void *) arg,
905					       sizeof(toc_entry));
906
907				if (toc_entry.cdte_track == CDROM_LEADOUT)
908					tp = &sjcd_table_of_contents[0];
909				else if (toc_entry.cdte_track <
910					 sjcd_first_track_no)
911					return (-EINVAL);
912				else if (toc_entry.cdte_track >
913					 sjcd_last_track_no)
914					return (-EINVAL);
915				else
916					tp = &sjcd_table_of_contents
917					    [toc_entry.cdte_track];
918
919				toc_entry.cdte_adr =
920				    tp->track_control & 0x0F;
921				toc_entry.cdte_ctrl =
922				    tp->track_control >> 4;
923
924				switch (toc_entry.cdte_format) {
925				case CDROM_LBA:
926					toc_entry.cdte_addr.lba =
927					    msf2hsg(&(tp->un.track_msf));
928					break;
929				case CDROM_MSF:
930					toc_entry.cdte_addr.msf.minute =
931					    bcd2bin(tp->un.track_msf.min);
932					toc_entry.cdte_addr.msf.second =
933					    bcd2bin(tp->un.track_msf.sec);
934					toc_entry.cdte_addr.msf.frame =
935					    bcd2bin(tp->un.track_msf.
936						    frame);
937					break;
938				default:
939					return (-EINVAL);
940				}
941				copy_to_user((void *) arg, &toc_entry,
942					     sizeof(toc_entry));
943			}
944			return (s);
945		}
946
947	case CDROMSUBCHNL:{
948			struct cdrom_subchnl subchnl;
949			int s;
950#if defined(SJCD_TRACE)
951			printk("SJCD: ioctl: subchnl\n");
952#endif
953			if ((s =
954			     verify_area(VERIFY_WRITE, (void *) arg,
955					 sizeof(subchnl))) == 0) {
956				struct sjcd_hw_qinfo q_info;
957
958				copy_from_user(&subchnl, (void *) arg,
959					       sizeof(subchnl));
960				if (sjcd_get_q_info(&q_info) < 0)
961					return (-EIO);
962
963				subchnl.cdsc_audiostatus =
964				    sjcd_audio_status;
965				subchnl.cdsc_adr =
966				    q_info.track_control & 0x0F;
967				subchnl.cdsc_ctrl =
968				    q_info.track_control >> 4;
969				subchnl.cdsc_trk =
970				    bcd2bin(q_info.track_no);
971				subchnl.cdsc_ind = bcd2bin(q_info.x);
972
973				switch (subchnl.cdsc_format) {
974				case CDROM_LBA:
975					subchnl.cdsc_absaddr.lba =
976					    msf2hsg(&(q_info.abs));
977					subchnl.cdsc_reladdr.lba =
978					    msf2hsg(&(q_info.rel));
979					break;
980				case CDROM_MSF:
981					subchnl.cdsc_absaddr.msf.minute =
982					    bcd2bin(q_info.abs.min);
983					subchnl.cdsc_absaddr.msf.second =
984					    bcd2bin(q_info.abs.sec);
985					subchnl.cdsc_absaddr.msf.frame =
986					    bcd2bin(q_info.abs.frame);
987					subchnl.cdsc_reladdr.msf.minute =
988					    bcd2bin(q_info.rel.min);
989					subchnl.cdsc_reladdr.msf.second =
990					    bcd2bin(q_info.rel.sec);
991					subchnl.cdsc_reladdr.msf.frame =
992					    bcd2bin(q_info.rel.frame);
993					break;
994				default:
995					return (-EINVAL);
996				}
997				copy_to_user((void *) arg, &subchnl,
998					     sizeof(subchnl));
999			}
1000			return (s);
1001		}
1002
1003	case CDROMVOLCTRL:{
1004			struct cdrom_volctrl vol_ctrl;
1005			int s;
1006#if defined(SJCD_TRACE)
1007			printk("SJCD: ioctl: volctrl\n");
1008#endif
1009			if ((s =
1010			     verify_area(VERIFY_READ, (void *) arg,
1011					 sizeof(vol_ctrl))) == 0) {
1012				unsigned char dummy[4];
1013
1014				copy_from_user(&vol_ctrl, (void *) arg,
1015					       sizeof(vol_ctrl));
1016				sjcd_send_4_cmd(SCMD_SET_VOLUME,
1017						vol_ctrl.channel0, 0xFF,
1018						vol_ctrl.channel1, 0xFF);
1019				if (sjcd_receive_status() < 0)
1020					return (-EIO);
1021				(void) sjcd_load_response(dummy, 4);
1022			}
1023			return (s);
1024		}
1025
1026	case CDROMEJECT:{
1027#if defined(SJCD_TRACE)
1028			printk("SJCD: ioctl: eject\n");
1029#endif
1030			if (!sjcd_command_is_in_progress) {
1031				sjcd_tray_unlock();
1032				sjcd_send_cmd(SCMD_EJECT_TRAY);
1033				(void) sjcd_receive_status();
1034			}
1035			return (0);
1036		}
1037
1038#if defined(SJCD_GATHER_STAT)
1039	case 0xABCD:{
1040			int s;
1041#if defined(SJCD_TRACE)
1042			printk("SJCD: ioctl: statistic\n");
1043#endif
1044			if ((s =
1045			     verify_area(VERIFY_WRITE, (void *) arg,
1046					 sizeof(statistic))) == 0)
1047				copy_to_user((void *) arg, &statistic,
1048					     sizeof(statistic));
1049			return (s);
1050		}
1051#endif
1052
1053	default:
1054		return (-EINVAL);
1055	}
1056}
1057
1058/*
1059 * Invalidate internal buffers of the driver.
1060 */
1061static void sjcd_invalidate_buffers(void)
1062{
1063	int i;
1064	for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
1065	sjcd_buf_out = -1;
1066}
1067
1068/*
1069 * Take care of the different block sizes between cdrom and Linux.
1070 * When Linux gets variable block sizes this will probably go away.
1071 */
1072
1073#define CURRENT_IS_VALID                                      \
1074    ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \
1075      CURRENT->cmd == READ && CURRENT->sector != -1 )
1076
1077static void sjcd_transfer(void)
1078{
1079#if defined(SJCD_TRACE)
1080	printk("SJCD: transfer:\n");
1081#endif
1082	if (CURRENT_IS_VALID) {
1083		while (CURRENT->nr_sectors) {
1084			int i, bn = CURRENT->sector / 4;
1085			for (i = 0;
1086			     i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
1087			     i++);
1088			if (i < SJCD_BUF_SIZ) {
1089				int offs =
1090				    (i * 4 + (CURRENT->sector & 3)) * 512;
1091				int nr_sectors = 4 - (CURRENT->sector & 3);
1092				if (sjcd_buf_out != i) {
1093					sjcd_buf_out = i;
1094					if (sjcd_buf_bn[i] != bn) {
1095						sjcd_buf_out = -1;
1096						continue;
1097					}
1098				}
1099				if (nr_sectors > CURRENT->nr_sectors)
1100					nr_sectors = CURRENT->nr_sectors;
1101#if defined(SJCD_TRACE)
1102				printk("SJCD: copy out\n");
1103#endif
1104				memcpy(CURRENT->buffer, sjcd_buf + offs,
1105				       nr_sectors * 512);
1106				CURRENT->nr_sectors -= nr_sectors;
1107				CURRENT->sector += nr_sectors;
1108				CURRENT->buffer += nr_sectors * 512;
1109			} else {
1110				sjcd_buf_out = -1;
1111				break;
1112			}
1113		}
1114	}
1115#if defined(SJCD_TRACE)
1116	printk("SJCD: transfer: done\n");
1117#endif
1118}
1119
1120static void sjcd_poll(void)
1121{
1122#if defined(SJCD_GATHER_STAT)
1123	/*
1124	 * Update total number of ticks.
1125	 */
1126	statistic.ticks++;
1127	statistic.tticks[sjcd_transfer_state]++;
1128#endif
1129
1130      ReSwitch:switch (sjcd_transfer_state) {
1131
1132	case SJCD_S_IDLE:{
1133#if defined(SJCD_GATHER_STAT)
1134			statistic.idle_ticks++;
1135#endif
1136#if defined(SJCD_TRACE)
1137			printk("SJCD_S_IDLE\n");
1138#endif
1139			return;
1140		}
1141
1142	case SJCD_S_START:{
1143#if defined(SJCD_GATHER_STAT)
1144			statistic.start_ticks++;
1145#endif
1146			sjcd_send_cmd(SCMD_GET_STATUS);
1147			sjcd_transfer_state =
1148			    sjcd_mode ==
1149			    SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
1150			sjcd_transfer_timeout = 500;
1151#if defined(SJCD_TRACE)
1152			printk("SJCD_S_START: goto SJCD_S_%s mode\n",
1153			       sjcd_transfer_state ==
1154			       SJCD_S_READ ? "READ" : "MODE");
1155#endif
1156			break;
1157		}
1158
1159	case SJCD_S_MODE:{
1160			if (sjcd_check_status()) {
1161				/*
1162				 * Previous command is completed.
1163				 */
1164				if (!sjcd_status_valid
1165				    || sjcd_command_failed) {
1166#if defined(SJCD_TRACE)
1167					printk
1168					    ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
1169#endif
1170					sjcd_transfer_state = SJCD_S_STOP;
1171					goto ReSwitch;
1172				}
1173
1174				sjcd_mode = 0;	/* unknown mode; should not be valid when failed */
1175				sjcd_send_1_cmd(SCMD_SET_MODE,
1176						SCMD_MODE_COOKED);
1177				sjcd_transfer_state = SJCD_S_READ;
1178				sjcd_transfer_timeout = 1000;
1179#if defined(SJCD_TRACE)
1180				printk
1181				    ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
1182#endif
1183			}
1184#if defined(SJCD_GATHER_STAT)
1185			else
1186				statistic.mode_ticks++;
1187#endif
1188			break;
1189		}
1190
1191	case SJCD_S_READ:{
1192			if (sjcd_status_valid ? 1 : sjcd_check_status()) {
1193				/*
1194				 * Previous command is completed.
1195				 */
1196				if (!sjcd_status_valid
1197				    || sjcd_command_failed) {
1198#if defined(SJCD_TRACE)
1199					printk
1200					    ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
1201#endif
1202					sjcd_transfer_state = SJCD_S_STOP;
1203					goto ReSwitch;
1204				}
1205				if (!sjcd_media_is_available) {
1206#if defined(SJCD_TRACE)
1207					printk
1208					    ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
1209#endif
1210					sjcd_transfer_state = SJCD_S_STOP;
1211					goto ReSwitch;
1212				}
1213				if (sjcd_mode != SCMD_MODE_COOKED) {
1214					/*
1215					 * We seem to come from set mode. So discard one byte of result.
1216					 */
1217					if (sjcd_load_response
1218					    (&sjcd_mode, 1) != 0) {
1219#if defined(SJCD_TRACE)
1220						printk
1221						    ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
1222#endif
1223						sjcd_transfer_state =
1224						    SJCD_S_STOP;
1225						goto ReSwitch;
1226					}
1227					if (sjcd_mode != SCMD_MODE_COOKED) {
1228#if defined(SJCD_TRACE)
1229						printk
1230						    ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
1231#endif
1232						sjcd_transfer_state =
1233						    SJCD_S_STOP;
1234						goto ReSwitch;
1235					}
1236				}
1237
1238				if (CURRENT_IS_VALID) {
1239					struct sjcd_play_msf msf;
1240
1241					sjcd_next_bn = CURRENT->sector / 4;
1242					hsg2msf(sjcd_next_bn, &msf.start);
1243					msf.end.min = 0;
1244					msf.end.sec = 0;
1245					msf.end.frame = sjcd_read_count =
1246					    SJCD_BUF_SIZ;
1247#if defined(SJCD_TRACE)
1248					printk
1249					    ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",
1250					     msf.start.min, msf.start.sec,
1251					     msf.start.frame, msf.end.min,
1252					     msf.end.sec, msf.end.frame);
1253					printk
1254					    ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
1255					     sjcd_next_bn, sjcd_buf_in,
1256					     sjcd_buf_out,
1257					     sjcd_buf_bn[sjcd_buf_in]);
1258#endif
1259					sjcd_send_6_cmd(SCMD_DATA_READ,
1260							&msf);
1261					sjcd_transfer_state = SJCD_S_DATA;
1262					sjcd_transfer_timeout = 500;
1263#if defined(SJCD_TRACE)
1264					printk
1265					    ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
1266#endif
1267				} else {
1268#if defined(SJCD_TRACE)
1269					printk
1270					    ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
1271#endif
1272					sjcd_transfer_state = SJCD_S_STOP;
1273					goto ReSwitch;
1274				}
1275			}
1276#if defined(SJCD_GATHER_STAT)
1277			else
1278				statistic.read_ticks++;
1279#endif
1280			break;
1281		}
1282
1283	case SJCD_S_DATA:{
1284			unsigned char stat;
1285
1286		      sjcd_s_data:stat =
1287			    inb(SJCDPORT
1288				(1));
1289#if defined(SJCD_TRACE)
1290			printk("SJCD_S_DATA: status = 0x%02x\n", stat);
1291#endif
1292			if (SJCD_STATUS_AVAILABLE(stat)) {
1293				/*
1294				 * No data is waiting for us in the drive buffer. Status of operation
1295				 * completion is available. Read and parse it.
1296				 */
1297				sjcd_load_status();
1298
1299				if (!sjcd_status_valid
1300				    || sjcd_command_failed) {
1301#if defined(SJCD_TRACE)
1302					printk
1303					    ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
1304					     sjcd_next_bn);
1305#endif
1306					if (CURRENT_IS_VALID)
1307						end_request(0);
1308#if defined(SJCD_TRACE)
1309					printk
1310					    ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
1311#endif
1312					sjcd_transfer_state = SJCD_S_STOP;
1313					goto ReSwitch;
1314				}
1315
1316				if (!sjcd_media_is_available) {
1317					printk
1318					    ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
1319					sjcd_transfer_state = SJCD_S_STOP;
1320					goto ReSwitch;
1321				}
1322
1323				sjcd_transfer_state = SJCD_S_READ;
1324				goto ReSwitch;
1325			} else if (SJCD_DATA_AVAILABLE(stat)) {
1326				/*
1327				 * One frame is read into device buffer. We must copy it to our memory.
1328				 * Otherwise cdrom hangs up. Check to see if we have something to copy
1329				 * to.
1330				 */
1331				if (!CURRENT_IS_VALID
1332				    && sjcd_buf_in == sjcd_buf_out) {
1333#if defined(SJCD_TRACE)
1334					printk
1335					    ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
1336					printk
1337					    (" ... all the date would be discarded\n");
1338#endif
1339					sjcd_transfer_state = SJCD_S_STOP;
1340					goto ReSwitch;
1341				}
1342
1343				/*
1344				 * Everything seems to be OK. Just read the frame and recalculate
1345				 * indices.
1346				 */
1347				sjcd_buf_bn[sjcd_buf_in] = -1;	/* ??? */
1348				insb(SJCDPORT(2),
1349				     sjcd_buf + 2048 * sjcd_buf_in, 2048);
1350#if defined(SJCD_TRACE)
1351				printk
1352				    ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
1353				     sjcd_next_bn, sjcd_buf_in,
1354				     sjcd_buf_out,
1355				     sjcd_buf_bn[sjcd_buf_in]);
1356#endif
1357				sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
1358				if (sjcd_buf_out == -1)
1359					sjcd_buf_out = sjcd_buf_in;
1360				if (++sjcd_buf_in == SJCD_BUF_SIZ)
1361					sjcd_buf_in = 0;
1362
1363				/*
1364				 * Only one frame is ready at time. So we should turn over to wait for
1365				 * another frame. If we need that, of course.
1366				 */
1367				if (--sjcd_read_count == 0) {
1368					/*
1369					 * OK, request seems to be precessed. Continue transferring...
1370					 */
1371					if (!sjcd_transfer_is_active) {
1372						while (CURRENT_IS_VALID) {
1373							/*
1374							 * Continue transferring.
1375							 */
1376							sjcd_transfer();
1377							if (CURRENT->
1378							    nr_sectors ==
1379							    0)
1380								end_request
1381								    (1);
1382							else
1383								break;
1384						}
1385					}
1386					if (CURRENT_IS_VALID &&
1387					    (CURRENT->sector / 4 <
1388					     sjcd_next_bn
1389					     || CURRENT->sector / 4 >
1390					     sjcd_next_bn +
1391					     SJCD_BUF_SIZ)) {
1392#if defined(SJCD_TRACE)
1393						printk
1394						    ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
1395#endif
1396						sjcd_transfer_state =
1397						    SJCD_S_STOP;
1398						goto ReSwitch;
1399					}
1400				}
1401				/*
1402				 * Now we should turn around rather than wait for while.
1403				 */
1404				goto sjcd_s_data;
1405			}
1406#if defined(SJCD_GATHER_STAT)
1407			else
1408				statistic.data_ticks++;
1409#endif
1410			break;
1411		}
1412
1413	case SJCD_S_STOP:{
1414			sjcd_read_count = 0;
1415			sjcd_send_cmd(SCMD_STOP);
1416			sjcd_transfer_state = SJCD_S_STOPPING;
1417			sjcd_transfer_timeout = 500;
1418#if defined(SJCD_GATHER_STAT)
1419			statistic.stop_ticks++;
1420#endif
1421			break;
1422		}
1423
1424	case SJCD_S_STOPPING:{
1425			unsigned char stat;
1426
1427			stat = inb(SJCDPORT(1));
1428#if defined(SJCD_TRACE)
1429			printk("SJCD_S_STOP: status = 0x%02x\n", stat);
1430#endif
1431			if (SJCD_DATA_AVAILABLE(stat)) {
1432				int i;
1433#if defined(SJCD_TRACE)
1434				printk("SJCD_S_STOP: discard data\n");
1435#endif
1436				/*
1437				 * Discard all the data from the pipe. Foolish method.
1438				 */
1439				for (i = 2048; i--;
1440				     (void) inb(SJCDPORT(2)));
1441				sjcd_transfer_timeout = 500;
1442			} else if (SJCD_STATUS_AVAILABLE(stat)) {
1443				sjcd_load_status();
1444				if (sjcd_status_valid
1445				    && sjcd_media_is_changed) {
1446					sjcd_toc_uptodate = 0;
1447					sjcd_invalidate_buffers();
1448				}
1449				if (CURRENT_IS_VALID) {
1450					if (sjcd_status_valid)
1451						sjcd_transfer_state =
1452						    SJCD_S_READ;
1453					else
1454						sjcd_transfer_state =
1455						    SJCD_S_START;
1456				} else
1457					sjcd_transfer_state = SJCD_S_IDLE;
1458				goto ReSwitch;
1459			}
1460#if defined(SJCD_GATHER_STAT)
1461			else
1462				statistic.stopping_ticks++;
1463#endif
1464			break;
1465		}
1466
1467	default:
1468		printk("SJCD: poll: invalid state %d\n",
1469		       sjcd_transfer_state);
1470		return;
1471	}
1472
1473	if (--sjcd_transfer_timeout == 0) {
1474		printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
1475		while (CURRENT_IS_VALID)
1476			end_request(0);
1477		sjcd_send_cmd(SCMD_STOP);
1478		sjcd_transfer_state = SJCD_S_IDLE;
1479		goto ReSwitch;
1480	}
1481
1482	/*
1483	 * Get back in some time. 1 should be replaced with count variable to
1484	 * avoid unnecessary testings.
1485	 */
1486	SJCD_SET_TIMER(sjcd_poll, 1);
1487}
1488
1489static void do_sjcd_request(request_queue_t * q)
1490{
1491#if defined(SJCD_TRACE)
1492	printk("SJCD: do_sjcd_request(%ld+%ld)\n",
1493	       CURRENT->sector, CURRENT->nr_sectors);
1494#endif
1495	sjcd_transfer_is_active = 1;
1496	while (CURRENT_IS_VALID) {
1497		/*
1498		 * Who of us are paranoiac?
1499		 */
1500		if (CURRENT->bh && !buffer_locked(CURRENT->bh))
1501			panic(DEVICE_NAME ": block not locked");
1502
1503		sjcd_transfer();
1504		if (CURRENT->nr_sectors == 0)
1505			end_request(1);
1506		else {
1507			sjcd_buf_out = -1;	/* Want to read a block not in buffer */
1508			if (sjcd_transfer_state == SJCD_S_IDLE) {
1509				if (!sjcd_toc_uptodate) {
1510					if (sjcd_update_toc() < 0) {
1511						printk
1512						    ("SJCD: transfer: discard\n");
1513						while (CURRENT_IS_VALID)
1514							end_request(0);
1515						break;
1516					}
1517				}
1518				sjcd_transfer_state = SJCD_S_START;
1519				SJCD_SET_TIMER(sjcd_poll, HZ / 100);
1520			}
1521			break;
1522		}
1523	}
1524	sjcd_transfer_is_active = 0;
1525#if defined(SJCD_TRACE)
1526	printk
1527	    ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
1528	     sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
1529	     sjcd_buf_bn[sjcd_buf_in]);
1530	printk("do_sjcd_request ends\n");
1531#endif
1532}
1533
1534/*
1535 * Open the device special file. Check disk is in.
1536 */
1537int sjcd_open(struct inode *ip, struct file *fp)
1538{
1539	/*
1540	 * Check the presence of device.
1541	 */
1542	if (!sjcd_present)
1543		return (-ENXIO);
1544
1545	/*
1546	 * Only read operations are allowed. Really? (:-)
1547	 */
1548	if (fp->f_mode & 2)
1549		return (-EROFS);
1550
1551	if (sjcd_open_count == 0) {
1552		int s, sjcd_open_tries;
1553/* We don't know that, do we? */
1554/*
1555    sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
1556*/
1557		sjcd_mode = 0;
1558		sjcd_door_was_open = 0;
1559		sjcd_transfer_state = SJCD_S_IDLE;
1560		sjcd_invalidate_buffers();
1561		sjcd_status_valid = 0;
1562
1563		/*
1564		 * Strict status checking.
1565		 */
1566		for (sjcd_open_tries = 4; --sjcd_open_tries;) {
1567			if (!sjcd_status_valid)
1568				sjcd_get_status();
1569			if (!sjcd_status_valid) {
1570#if defined(SJCD_DIAGNOSTIC)
1571				printk
1572				    ("SJCD: open: timed out when check status.\n");
1573#endif
1574				goto err_out;
1575			} else if (!sjcd_media_is_available) {
1576#if defined(SJCD_DIAGNOSTIC)
1577				printk("SJCD: open: no disk in drive\n");
1578#endif
1579				if (!sjcd_door_closed) {
1580					sjcd_door_was_open = 1;
1581#if defined(SJCD_TRACE)
1582					printk
1583					    ("SJCD: open: close the tray\n");
1584#endif
1585					s = sjcd_tray_close();
1586					if (s < 0 || !sjcd_status_valid
1587					    || sjcd_command_failed) {
1588#if defined(SJCD_DIAGNOSTIC)
1589						printk
1590						    ("SJCD: open: tray close attempt failed\n");
1591#endif
1592						goto err_out;
1593					}
1594					continue;
1595				} else
1596					goto err_out;
1597			}
1598			break;
1599		}
1600		s = sjcd_tray_lock();
1601		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
1602#if defined(SJCD_DIAGNOSTIC)
1603			printk("SJCD: open: tray lock attempt failed\n");
1604#endif
1605			goto err_out;
1606		}
1607#if defined(SJCD_TRACE)
1608		printk("SJCD: open: done\n");
1609#endif
1610	}
1611
1612	++sjcd_open_count;
1613	return (0);
1614
1615      err_out:
1616	return (-EIO);
1617}
1618
1619/*
1620 * On close, we flush all sjcd blocks from the buffer cache.
1621 */
1622static int sjcd_release(struct inode *inode, struct file *file)
1623{
1624	int s;
1625
1626#if defined(SJCD_TRACE)
1627	printk("SJCD: release\n");
1628#endif
1629	if (--sjcd_open_count == 0) {
1630		sjcd_invalidate_buffers();
1631		s = sjcd_tray_unlock();
1632		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
1633#if defined(SJCD_DIAGNOSTIC)
1634			printk
1635			    ("SJCD: release: tray unlock attempt failed.\n");
1636#endif
1637		}
1638		if (sjcd_door_was_open) {
1639			s = sjcd_tray_open();
1640			if (s < 0 || !sjcd_status_valid
1641			    || sjcd_command_failed) {
1642#if defined(SJCD_DIAGNOSTIC)
1643				printk
1644				    ("SJCD: release: tray unload attempt failed.\n");
1645#endif
1646			}
1647		}
1648	}
1649	return 0;
1650}
1651
1652/*
1653 * A list of file operations allowed for this cdrom.
1654 */
1655static struct block_device_operations sjcd_fops = {
1656	owner:THIS_MODULE,
1657	open:sjcd_open,
1658	release:sjcd_release,
1659	ioctl:sjcd_ioctl,
1660	check_media_change:sjcd_disk_change,
1661};
1662
1663static int blksize = 2048;
1664static int secsize = 2048;
1665
1666/*
1667 * Following stuff is intended for initialization of the cdrom. It
1668 * first looks for presence of device. If the device is present, it
1669 * will be reset. Then read the version of the drive and load status.
1670 * The version is two BCD-coded bytes.
1671 */
1672static struct {
1673	unsigned char major, minor;
1674} sjcd_version;
1675
1676/*
1677 * Test for presence of drive and initialize it. Called at boot time.
1678 * Probe cdrom, find out version and status.
1679 */
1680int __init sjcd_init(void)
1681{
1682	int i;
1683
1684	printk(KERN_INFO
1685	       "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
1686	       SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
1687
1688#if defined(SJCD_TRACE)
1689	printk("SJCD: sjcd=0x%x: ", sjcd_base);
1690#endif
1691
1692	hardsect_size[MAJOR_NR] = &secsize;
1693	blksize_size[MAJOR_NR] = &blksize;
1694
1695	if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
1696		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",
1697		       MAJOR_NR);
1698		return (-EIO);
1699	}
1700
1701	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1702	read_ahead[MAJOR_NR] = 4;
1703	register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0);
1704
1705	if (check_region(sjcd_base, 4)) {
1706		printk
1707		    ("SJCD: Init failed, I/O port (%X) is already in use\n",
1708		     sjcd_base);
1709		sjcd_cleanup();
1710		return (-EIO);
1711	}
1712
1713	/*
1714	 * Check for card. Since we are booting now, we can't use standard
1715	 * wait algorithm.
1716	 */
1717	printk(KERN_INFO "SJCD: Resetting: ");
1718	sjcd_send_cmd(SCMD_RESET);
1719	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
1720		unsigned long timer;
1721
1722		/*
1723		 * Wait 10ms approx.
1724		 */
1725		for (timer = jiffies; time_before_eq(jiffies, timer););
1726		if ((i % 100) == 0)
1727			printk(".");
1728		(void) sjcd_check_status();
1729	}
1730	if (i == 0 || sjcd_command_failed) {
1731		printk(" reset failed, no drive found.\n");
1732		sjcd_cleanup();
1733		return (-EIO);
1734	} else
1735		printk("\n");
1736
1737	/*
1738	 * Get and print out cdrom version.
1739	 */
1740	printk(KERN_INFO "SJCD: Getting version: ");
1741	sjcd_send_cmd(SCMD_GET_VERSION);
1742	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
1743		unsigned long timer;
1744
1745		/*
1746		 * Wait 10ms approx.
1747		 */
1748		for (timer = jiffies; time_before_eq(jiffies, timer););
1749		if ((i % 100) == 0)
1750			printk(".");
1751		(void) sjcd_check_status();
1752	}
1753	if (i == 0 || sjcd_command_failed) {
1754		printk(" get version failed, no drive found.\n");
1755		sjcd_cleanup();
1756		return (-EIO);
1757	}
1758
1759	if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
1760		printk(" %1x.%02x\n", (int) sjcd_version.major,
1761		       (int) sjcd_version.minor);
1762	} else {
1763		printk(" read version failed, no drive found.\n");
1764		sjcd_cleanup();
1765		return (-EIO);
1766	}
1767
1768	/*
1769	 * Check and print out the tray state. (if it is needed?).
1770	 */
1771	if (!sjcd_status_valid) {
1772		printk(KERN_INFO "SJCD: Getting status: ");
1773		sjcd_send_cmd(SCMD_GET_STATUS);
1774		for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
1775			unsigned long timer;
1776
1777			/*
1778			 * Wait 10ms approx.
1779			 */
1780			for (timer = jiffies;
1781			     time_before_eq(jiffies, timer););
1782			if ((i % 100) == 0)
1783				printk(".");
1784			(void) sjcd_check_status();
1785		}
1786		if (i == 0 || sjcd_command_failed) {
1787			printk(" get status failed, no drive found.\n");
1788			sjcd_cleanup();
1789			return (-EIO);
1790		} else
1791			printk("\n");
1792	}
1793
1794	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
1795	devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
1796		       S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
1797
1798	sjcd_present++;
1799	return (0);
1800}
1801
1802static int sjcd_cleanup(void)
1803{
1804	if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
1805		printk("SJCD: cannot unregister device.\n");
1806	else {
1807		release_region(sjcd_base, 4);
1808		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1809	}
1810
1811	return (0);
1812}
1813
1814
1815void __exit sjcd_exit(void)
1816{
1817	devfs_unregister(devfs_find_handle
1818			 (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0));
1819	if (sjcd_cleanup())
1820		printk("SJCD: module: cannot be removed.\n");
1821	else
1822		printk(KERN_INFO "SJCD: module: removed.\n");
1823}
1824
1825#ifdef MODULE
1826module_init(sjcd_init);
1827#endif
1828module_exit(sjcd_exit);
1829
1830
1831MODULE_LICENSE("GPL");
1832