File: /usr/src/linux/drivers/cdrom/gscd.c

1     #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
2     
3     /*
4     	linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
5     
6             Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
7             based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
8             
9     
10             For all kind of other information about the GoldStar CDROM
11             and this Linux device driver I installed a WWW-URL:
12             http://linux.rz.fh-hannover.de/~raupach        
13     
14     
15                  If you are the editor of a Linux CD, you should
16                  enable gscd.c within your boot floppy kernel and
17                  send me one of your CDs for free.
18     
19     
20             --------------------------------------------------------------------
21     	This program is free software; you can redistribute it and/or modify
22     	it under the terms of the GNU General Public License as published by
23     	the Free Software Foundation; either version 2, or (at your option)
24     	any later version.
25     
26     	This program is distributed in the hope that it will be useful,
27     	but WITHOUT ANY WARRANTY; without even the implied warranty of
28     	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29     	GNU General Public License for more details.
30     
31     	You should have received a copy of the GNU General Public License
32     	along with this program; if not, write to the Free Software
33     	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34     	
35     	--------------------------------------------------------------------
36     	
37     	9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
38     	                   Removed init_module & cleanup_module in favor of 
39     		   	   module_init & module_exit.
40     			   Torben Mathiasen <tmm@image.dk>
41     
42     */
43     
44     /* These settings are for various debug-level. Leave they untouched ... */
45     #define  NO_GSCD_DEBUG
46     #define  NO_IOCTL_DEBUG
47     #define  NO_MODULE_DEBUG
48     #define  NO_FUTURE_WORK
49     /*------------------------*/
50     
51     #include <linux/module.h>
52     
53     #include <linux/slab.h>
54     #include <linux/errno.h>
55     #include <linux/signal.h>
56     #include <linux/sched.h>
57     #include <linux/timer.h>
58     #include <linux/fs.h>
59     #include <linux/mm.h>
60     #include <linux/kernel.h>
61     #include <linux/cdrom.h>
62     #include <linux/ioport.h>
63     #include <linux/major.h>
64     #include <linux/string.h>
65     #include <linux/init.h>
66     #include <linux/devfs_fs_kernel.h>
67     
68     #include <asm/system.h>
69     #include <asm/io.h>
70     #include <asm/uaccess.h>
71     
72     #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
73     #include <linux/blk.h>
74     #define gscd_port gscd		/* for compatible parameter passing with "insmod" */
75     #include "gscd.h"
76     
77     static int gscd_blocksizes[1] = { 512 };
78     
79     static int gscdPresent = 0;
80     
81     static unsigned char gscd_buf[2048];	/* buffer for block size conversion */
82     static int gscd_bn = -1;
83     static short gscd_port = GSCD_BASE_ADDR;
84     MODULE_PARM(gscd, "h");
85     
86     /* Kommt spaeter vielleicht noch mal dran ...
87      *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
88      */
89     
90     static void gscd_transfer(void);
91     static void gscd_read_cmd(void);
92     static void gscd_hsg2msf(long hsg, struct msf *msf);
93     static void gscd_bin2bcd(unsigned char *p);
94     
95     /* Schnittstellen zum Kern/FS */
96     
97     static void do_gscd_request(request_queue_t *);
98     static void __do_gscd_request(unsigned long dummy);
99     static int gscd_ioctl(struct inode *, struct file *, unsigned int,
100     		      unsigned long);
101     static int gscd_open(struct inode *, struct file *);
102     static int gscd_release(struct inode *, struct file *);
103     static int check_gscd_med_chg(kdev_t);
104     
105     /*      GoldStar Funktionen    */
106     
107     static void cc_Reset(void);
108     static int wait_drv_ready(void);
109     static int find_drives(void);
110     static void cmd_out(int, char *, char *, int);
111     static void cmd_status(void);
112     static void cc_Ident(char *);
113     static void cc_SetSpeed(void);
114     static void init_cd_drive(int);
115     
116     static int get_status(void);
117     static void clear_Audio(void);
118     static void cc_invalidate(void);
119     
120     /* some things for the next version */
121     #ifdef FUTURE_WORK
122     static void update_state(void);
123     static long gscd_msf2hsg(struct msf *mp);
124     static int gscd_bcd2bin(unsigned char bcd);
125     #endif
126     
127     /*    common GoldStar Initialization    */
128     
129     static int my_gscd_init(void);
130     
131     
132     /*      lo-level cmd-Funktionen    */
133     
134     static void cmd_info_in(char *, int);
135     static void cmd_end(void);
136     static void cmd_read_b(char *, int, int);
137     static void cmd_read_w(char *, int, int);
138     static int cmd_unit_alive(void);
139     static void cmd_write_cmd(char *);
140     
141     
142     /*      GoldStar Variablen     */
143     
144     static int curr_drv_state;
145     static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
146     static int drv_mode;
147     static int disk_state;
148     static int speed;
149     static int ndrives;
150     
151     static unsigned char drv_num_read;
152     static unsigned char f_dsk_valid;
153     static unsigned char current_drive;
154     static unsigned char f_drv_ok;
155     
156     
157     static char f_AudioPlay;
158     static char f_AudioPause;
159     static int AudioStart_m;
160     static int AudioStart_f;
161     static int AudioEnd_m;
162     static int AudioEnd_f;
163     
164     static struct timer_list gscd_timer;
165     
166     static struct block_device_operations gscd_fops = {
167     	open:gscd_open,
168     	release:gscd_release,
169     	ioctl:gscd_ioctl,
170     	check_media_change:check_gscd_med_chg,
171     };
172     
173     /* 
174      * Checking if the media has been changed
175      * (not yet implemented)
176      */
177     static int check_gscd_med_chg(kdev_t full_dev)
178     {
179     	int target;
180     
181     
182     	target = MINOR(full_dev);
183     
184     	if (target > 0) {
185     		printk
186     		    ("GSCD: GoldStar CD-ROM request error: invalid device.\n");
187     		return 0;
188     	}
189     #ifdef GSCD_DEBUG
190     	printk("gscd: check_med_change\n");
191     #endif
192     
193     	return 0;
194     }
195     
196     
197     #ifndef MODULE
198     /* Using new interface for kernel-parameters */
199     
200     static int __init gscd_setup(char *str)
201     {
202     	int ints[2];
203     	(void) get_options(str, ARRAY_SIZE(ints), ints);
204     
205     	if (ints[0] > 0) {
206     		gscd_port = ints[1];
207     	}
208     	return 1;
209     }
210     
211     __setup("gscd=", gscd_setup);
212     
213     #endif
214     
215     static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
216     		      unsigned long arg)
217     {
218     	unsigned char to_do[10];
219     	unsigned char dummy;
220     
221     
222     	switch (cmd) {
223     	case CDROMSTART:	/* Spin up the drive */
224     		/* Don't think we can do this.  Even if we could,
225     		 * I think the drive times out and stops after a while
226     		 * anyway.  For now, ignore it.
227     		 */
228     		return 0;
229     
230     	case CDROMRESUME:	/* keine Ahnung was das ist */
231     		return 0;
232     
233     
234     	case CDROMEJECT:
235     		cmd_status();
236     		to_do[0] = CMD_TRAY_CTL;
237     		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
238     
239     		return 0;
240     
241     	default:
242     		return -EINVAL;
243     	}
244     
245     }
246     
247     
248     /*
249      * Take care of the different block sizes between cdrom and Linux.
250      * When Linux gets variable block sizes this will probably go away.
251      */
252     
253     static void gscd_transfer(void)
254     {
255     	long offs;
256     
257     	while (CURRENT->nr_sectors > 0 && gscd_bn == CURRENT->sector / 4) {
258     		offs = (CURRENT->sector & 3) * 512;
259     		memcpy(CURRENT->buffer, gscd_buf + offs, 512);
260     		CURRENT->nr_sectors--;
261     		CURRENT->sector++;
262     		CURRENT->buffer += 512;
263     	}
264     }
265     
266     
267     /*
268      * I/O request routine called from Linux kernel.
269      */
270     
271     static void do_gscd_request(request_queue_t * q)
272     {
273     	__do_gscd_request(0);
274     }
275     
276     static void __do_gscd_request(unsigned long dummy)
277     {
278     	unsigned int block, dev;
279     	unsigned int nsect;
280     
281           repeat:
282     	if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE)
283     		goto out;
284     	INIT_REQUEST;
285     	dev = MINOR(CURRENT->rq_dev);
286     	block = CURRENT->sector;
287     	nsect = CURRENT->nr_sectors;
288     
289     	if (QUEUE_EMPTY || CURRENT->sector == -1)
290     		goto out;
291     
292     	if (CURRENT->cmd != READ) {
293     		printk("GSCD: bad cmd %d\n", CURRENT->cmd);
294     		end_request(0);
295     		goto repeat;
296     	}
297     
298     	if (MINOR(CURRENT->rq_dev) != 0) {
299     		printk("GSCD: this version supports only one device\n");
300     		end_request(0);
301     		goto repeat;
302     	}
303     
304     	gscd_transfer();
305     
306     	/* if we satisfied the request from the buffer, we're done. */
307     
308     	if (CURRENT->nr_sectors == 0) {
309     		end_request(1);
310     		goto repeat;
311     	}
312     #ifdef GSCD_DEBUG
313     	printk("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect);
314     #endif
315     
316     	gscd_read_cmd();
317           out:
318     	return;
319     }
320     
321     
322     
323     /*
324      * Check the result of the set-mode command.  On success, send the
325      * read-data command.
326      */
327     
328     static void gscd_read_cmd(void)
329     {
330     	long block;
331     	struct gscd_Play_msf gscdcmd;
332     	char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 };	/* cmd mode M-S-F secth sectl */
333     
334     
335     
336     	cmd_status();
337     	if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
338     		printk("GSCD: no disk or door open\n");
339     		end_request(0);
340     	} else {
341     		if (disk_state & ST_INVALID) {
342     			printk("GSCD: disk invalid\n");
343     			end_request(0);
344     		} else {
345     			gscd_bn = -1;	/* purge our buffer */
346     			block = CURRENT->sector / 4;
347     			gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */
348     
349     			cmd[2] = gscdcmd.start.min;
350     			cmd[3] = gscdcmd.start.sec;
351     			cmd[4] = gscdcmd.start.frame;
352     
353     #ifdef GSCD_DEBUG
354     			printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
355     			       cmd[4]);
356     #endif
357     			cmd_out(TYPE_DATA, (char *) &cmd,
358     				(char *) &gscd_buf[0], 1);
359     
360     			gscd_bn = CURRENT->sector / 4;
361     			gscd_transfer();
362     			end_request(1);
363     		}
364     	}
365     	SET_TIMER(__do_gscd_request, 1);
366     }
367     
368     
369     /*
370      * Open the device special file.  Check that a disk is in.
371      */
372     
373     static int gscd_open(struct inode *ip, struct file *fp)
374     {
375     	int st;
376     
377     #ifdef GSCD_DEBUG
378     	printk("GSCD: open\n");
379     #endif
380     
381     	if (gscdPresent == 0)
382     		return -ENXIO;	/* no hardware */
383     
384     	MOD_INC_USE_COUNT;
385     
386     	get_status();
387     	st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
388     	if (st) {
389     		printk("GSCD: no disk or door open\n");
390     		MOD_DEC_USE_COUNT;
391     		return -ENXIO;
392     	}
393     
394     /*	if (updateToc() < 0)
395     		return -EIO;
396     */
397     
398     	return 0;
399     }
400     
401     
402     /*
403      * On close, we flush all gscd blocks from the buffer cache.
404      */
405     
406     static int gscd_release(struct inode *inode, struct file *file)
407     {
408     
409     #ifdef GSCD_DEBUG
410     	printk("GSCD: release\n");
411     #endif
412     
413     	gscd_bn = -1;
414     
415     	MOD_DEC_USE_COUNT;
416     	return 0;
417     }
418     
419     
420     int get_status(void)
421     {
422     	int status;
423     
424     	cmd_status();
425     	status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
426     
427     	if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
428     		cc_invalidate();
429     		return 1;
430     	} else {
431     		return 0;
432     	}
433     }
434     
435     
436     void cc_invalidate(void)
437     {
438     	drv_num_read = 0xFF;
439     	f_dsk_valid = 0xFF;
440     	current_drive = 0xFF;
441     	f_drv_ok = 0xFF;
442     
443     	clear_Audio();
444     
445     }
446     
447     void clear_Audio(void)
448     {
449     
450     	f_AudioPlay = 0;
451     	f_AudioPause = 0;
452     	AudioStart_m = 0;
453     	AudioStart_f = 0;
454     	AudioEnd_m = 0;
455     	AudioEnd_f = 0;
456     
457     }
458     
459     /*
460      *   waiting ?  
461      */
462     
463     int wait_drv_ready(void)
464     {
465     	int found, read;
466     
467     	do {
468     		found = inb(GSCDPORT(0));
469     		found &= 0x0f;
470     		read = inb(GSCDPORT(0));
471     		read &= 0x0f;
472     	} while (read != found);
473     
474     #ifdef GSCD_DEBUG
475     	printk("Wait for: %d\n", read);
476     #endif
477     
478     	return read;
479     }
480     
481     void cc_Ident(char *respons)
482     {
483     	char to_do[] = { CMD_IDENT, 0, 0 };
484     
485     	cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
486     
487     }
488     
489     void cc_SetSpeed(void)
490     {
491     	char to_do[] = { CMD_SETSPEED, 0, 0 };
492     	char dummy;
493     
494     	if (speed > 0) {
495     		to_do[1] = speed & 0x0F;
496     		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
497     	}
498     }
499     
500     
501     void cc_Reset(void)
502     {
503     	char to_do[] = { CMD_RESET, 0 };
504     	char dummy;
505     
506     	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
507     }
508     
509     
510     
511     void cmd_status(void)
512     {
513     	char to_do[] = { CMD_STATUS, 0 };
514     	char dummy;
515     
516     	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
517     
518     #ifdef GSCD_DEBUG
519     	printk("GSCD: Status: %d\n", disk_state);
520     #endif
521     
522     }
523     
524     void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
525     {
526     	int result;
527     
528     
529     	result = wait_drv_ready();
530     	if (result != drv_mode) {
531     		unsigned long test_loops = 0xFFFF;
532     		int i, dummy;
533     
534     		outb(curr_drv_state, GSCDPORT(0));
535     
536     		/* LOCLOOP_170 */
537     		do {
538     			result = wait_drv_ready();
539     			test_loops--;
540     		} while ((result != drv_mode) && (test_loops > 0));
541     
542     		if (result != drv_mode) {
543     			disk_state = ST_x08 | ST_x04 | ST_INVALID;
544     			return;
545     		}
546     
547     		/* ...and waiting */
548     		for (i = 1, dummy = 1; i < 0xFFFF; i++) {
549     			dummy *= i;
550     		}
551     	}
552     
553     	/* LOC_172 */
554     	/* check the unit */
555     	/* and wake it up */
556     	if (cmd_unit_alive() != 0x08) {
557     		/* LOC_174 */
558     		/* game over for this unit */
559     		disk_state = ST_x08 | ST_x04 | ST_INVALID;
560     		return;
561     	}
562     
563     	/* LOC_176 */
564     #ifdef GSCD_DEBUG
565     	printk("LOC_176 ");
566     #endif
567     	if (drv_mode == 0x09) {
568     		/* magic... */
569     		printk("GSCD: magic ...\n");
570     		outb(result, GSCDPORT(2));
571     	}
572     
573     	/* write the command to the drive */
574     	cmd_write_cmd(cmd);
575     
576     	/* LOC_178 */
577     	for (;;) {
578     		result = wait_drv_ready();
579     		if (result != drv_mode) {
580     			/* LOC_179 */
581     			if (result == 0x04) {	/* Mode 4 */
582     				/* LOC_205 */
583     #ifdef GSCD_DEBUG
584     				printk("LOC_205 ");
585     #endif
586     				disk_state = inb(GSCDPORT(2));
587     
588     				do {
589     					result = wait_drv_ready();
590     				} while (result != drv_mode);
591     				return;
592     
593     			} else {
594     				if (result == 0x06) {	/* Mode 6 */
595     					/* LOC_181 */
596     #ifdef GSCD_DEBUG
597     					printk("LOC_181 ");
598     #endif
599     
600     					if (cmd_type == TYPE_DATA) {
601     						/* read data */
602     						/* LOC_184 */
603     						if (drv_mode == 9) {
604     							/* read the data to the buffer (word) */
605     
606     							/* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
607     							cmd_read_w
608     							    (respo_buf,
609     							     respo_count,
610     							     CD_FRAMESIZE /
611     							     2);
612     							return;
613     						} else {
614     							/* read the data to the buffer (byte) */
615     
616     							/* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
617     							cmd_read_b
618     							    (respo_buf,
619     							     respo_count,
620     							     CD_FRAMESIZE);
621     							return;
622     						}
623     					} else {
624     						/* read the info to the buffer */
625     						cmd_info_in(respo_buf,
626     							    respo_count);
627     						return;
628     					}
629     
630     					return;
631     				}
632     			}
633     
634     		} else {
635     			disk_state = ST_x08 | ST_x04 | ST_INVALID;
636     			return;
637     		}
638     	}			/* for (;;) */
639     
640     
641     #ifdef GSCD_DEBUG
642     	printk("\n");
643     #endif
644     }
645     
646     
647     static void cmd_write_cmd(char *pstr)
648     {
649     	int i, j;
650     
651     	/* LOC_177 */
652     #ifdef GSCD_DEBUG
653     	printk("LOC_177 ");
654     #endif
655     
656     	/* calculate the number of parameter */
657     	j = *pstr & 0x0F;
658     
659     	/* shift it out */
660     	for (i = 0; i < j; i++) {
661     		outb(*pstr, GSCDPORT(2));
662     		pstr++;
663     	}
664     }
665     
666     
667     static int cmd_unit_alive(void)
668     {
669     	int result;
670     	unsigned long max_test_loops;
671     
672     
673     	/* LOC_172 */
674     #ifdef GSCD_DEBUG
675     	printk("LOC_172 ");
676     #endif
677     
678     	outb(curr_drv_state, GSCDPORT(0));
679     	max_test_loops = 0xFFFF;
680     
681     	do {
682     		result = wait_drv_ready();
683     		max_test_loops--;
684     	} while ((result != 0x08) && (max_test_loops > 0));
685     
686     	return result;
687     }
688     
689     
690     static void cmd_info_in(char *pb, int count)
691     {
692     	int result;
693     	char read;
694     
695     
696     	/* read info */
697     	/* LOC_182 */
698     #ifdef GSCD_DEBUG
699     	printk("LOC_182 ");
700     #endif
701     
702     	do {
703     		read = inb(GSCDPORT(2));
704     		if (count > 0) {
705     			*pb = read;
706     			pb++;
707     			count--;
708     		}
709     
710     		/* LOC_183 */
711     		do {
712     			result = wait_drv_ready();
713     		} while (result == 0x0E);
714     	} while (result == 6);
715     
716     	cmd_end();
717     	return;
718     }
719     
720     
721     static void cmd_read_b(char *pb, int count, int size)
722     {
723     	int result;
724     	int i;
725     
726     
727     	/* LOC_188 */
728     	/* LOC_189 */
729     #ifdef GSCD_DEBUG
730     	printk("LOC_189 ");
731     #endif
732     
733     	do {
734     		do {
735     			result = wait_drv_ready();
736     		} while (result != 6 || result == 0x0E);
737     
738     		if (result != 6) {
739     			cmd_end();
740     			return;
741     		}
742     #ifdef GSCD_DEBUG
743     		printk("LOC_191 ");
744     #endif
745     
746     		for (i = 0; i < size; i++) {
747     			*pb = inb(GSCDPORT(2));
748     			pb++;
749     		}
750     		count--;
751     	} while (count > 0);
752     
753     	cmd_end();
754     	return;
755     }
756     
757     
758     static void cmd_end(void)
759     {
760     	int result;
761     
762     
763     	/* LOC_204 */
764     #ifdef GSCD_DEBUG
765     	printk("LOC_204 ");
766     #endif
767     
768     	do {
769     		result = wait_drv_ready();
770     		if (result == drv_mode) {
771     			return;
772     		}
773     	} while (result != 4);
774     
775     	/* LOC_205 */
776     #ifdef GSCD_DEBUG
777     	printk("LOC_205 ");
778     #endif
779     
780     	disk_state = inb(GSCDPORT(2));
781     
782     	do {
783     		result = wait_drv_ready();
784     	} while (result != drv_mode);
785     	return;
786     
787     }
788     
789     
790     static void cmd_read_w(char *pb, int count, int size)
791     {
792     	int result;
793     	int i;
794     
795     
796     #ifdef GSCD_DEBUG
797     	printk("LOC_185 ");
798     #endif
799     
800     	do {
801     		/* LOC_185 */
802     		do {
803     			result = wait_drv_ready();
804     		} while (result != 6 || result == 0x0E);
805     
806     		if (result != 6) {
807     			cmd_end();
808     			return;
809     		}
810     
811     		for (i = 0; i < size; i++) {
812     			/* na, hier muss ich noch mal drueber nachdenken */
813     			*pb = inw(GSCDPORT(2));
814     			pb++;
815     		}
816     		count--;
817     	} while (count > 0);
818     
819     	cmd_end();
820     	return;
821     }
822     
823     int __init find_drives(void)
824     {
825     	int *pdrv;
826     	int drvnum;
827     	int subdrv;
828     	int i;
829     
830     	speed = 0;
831     	pdrv = (int *) &drv_states;
832     	curr_drv_state = 0xFE;
833     	subdrv = 0;
834     	drvnum = 0;
835     
836     	for (i = 0; i < 8; i++) {
837     		subdrv++;
838     		cmd_status();
839     		disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
840     		if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
841     			/* LOC_240 */
842     			*pdrv = curr_drv_state;
843     			init_cd_drive(drvnum);
844     			pdrv++;
845     			drvnum++;
846     		} else {
847     			if (subdrv < 2) {
848     				continue;
849     			} else {
850     				subdrv = 0;
851     			}
852     		}
853     
854     /*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
855     /* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
856     		curr_drv_state *= 2;
857     		curr_drv_state |= 1;
858     #ifdef GSCD_DEBUG
859     		printk("DriveState: %d\n", curr_drv_state);
860     #endif
861     	}
862     
863     	ndrives = drvnum;
864     	return drvnum;
865     }
866     
867     void __init init_cd_drive(int num)
868     {
869     	char resp[50];
870     	int i;
871     
872     	printk("GSCD: init unit %d\n", num);
873     	cc_Ident((char *) &resp);
874     
875     	printk("GSCD: identification: ");
876     	for (i = 0; i < 0x1E; i++) {
877     		printk("%c", resp[i]);
878     	}
879     	printk("\n");
880     
881     	cc_SetSpeed();
882     
883     }
884     
885     #ifdef FUTURE_WORK
886     /* return_done */
887     static void update_state(void)
888     {
889     	unsigned int AX;
890     
891     
892     	if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
893     		if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
894     			AX = ST_INVALID;
895     		}
896     
897     		if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
898     		    == 0) {
899     			invalidate();
900     			f_drv_ok = 0;
901     		}
902     
903     		AX |= 0x8000;
904     	}
905     
906     	if (disk_state & ST_PLAYING) {
907     		AX |= 0x200;
908     	}
909     
910     	AX |= 0x100;
911     	/* pkt_esbx = AX; */
912     
913     	disk_state = 0;
914     
915     }
916     #endif
917     
918     /* Init for the Module-Version */
919     int init_gscd(void)
920     {
921     	long err;
922     
923     
924     	/* call the GoldStar-init */
925     	err = my_gscd_init();
926     
927     	if (err < 0) {
928     		return err;
929     	} else {
930     		printk(KERN_INFO "Happy GoldStar !\n");
931     		return 0;
932     	}
933     }
934     
935     void __exit exit_gscd(void)
936     {
937     	CLEAR_TIMER;
938     
939     	devfs_unregister(devfs_find_handle
940     			 (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0));
941     	if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
942     		printk("What's that: can't unregister GoldStar-module\n");
943     		return;
944     	}
945     	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
946     	release_region(gscd_port, 4);
947     	printk(KERN_INFO "GoldStar-module released.\n");
948     }
949     
950     #ifdef MODULE
951     module_init(init_gscd);
952     #endif
953     module_exit(exit_gscd);
954     
955     
956     /* Test for presence of drive and initialize it.  Called only at boot time. */
957     int __init gscd_init(void)
958     {
959     	return my_gscd_init();
960     }
961     
962     
963     /* This is the common initialisation for the GoldStar drive. */
964     /* It is called at boot time AND for module init.           */
965     int __init my_gscd_init(void)
966     {
967     	int i;
968     	int result;
969     
970     	printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
971     	printk(KERN_INFO
972     	       "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
973     	       gscd_port);
974     
975     	if (check_region(gscd_port, 4)) {
976     		printk
977     		    ("GSCD: Init failed, I/O port (%X) already in use.\n",
978     		     gscd_port);
979     		return -EIO;
980     	}
981     
982     
983     	/* check for card */
984     	result = wait_drv_ready();
985     	if (result == 0x09) {
986     		printk("GSCD: DMA kann ich noch nicht!\n");
987     		return -EIO;
988     	}
989     
990     	if (result == 0x0b) {
991     		drv_mode = result;
992     		i = find_drives();
993     		if (i == 0) {
994     			printk
995     			    ("GSCD: GoldStar CD-ROM Drive is not found.\n");
996     			return -EIO;
997     		}
998     	}
999     
1000     	if ((result != 0x0b) && (result != 0x09)) {
1001     		printk
1002     		    ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n");
1003     		return -EIO;
1004     	}
1005     
1006     	/* reset all drives */
1007     	i = 0;
1008     	while (drv_states[i] != 0) {
1009     		curr_drv_state = drv_states[i];
1010     		printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
1011     		cc_Reset();
1012     		printk("done\n");
1013     		i++;
1014     	}
1015     
1016     	if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
1017     		printk
1018     		    ("GSCD: Unable to get major %d for GoldStar CD-ROM\n",
1019     		     MAJOR_NR);
1020     		return -EIO;
1021     	}
1022     	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
1023     		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
1024     
1025     	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1026     	blksize_size[MAJOR_NR] = gscd_blocksizes;
1027     	read_ahead[MAJOR_NR] = 4;
1028     
1029     	disk_state = 0;
1030     	gscdPresent = 1;
1031     
1032     	request_region(gscd_port, 4, "gscd");
1033     	register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &gscd_fops, 0);
1034     
1035     	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
1036     	return 0;
1037     }
1038     
1039     static void gscd_hsg2msf(long hsg, struct msf *msf)
1040     {
1041     	hsg += CD_MSF_OFFSET;
1042     	msf->min = hsg / (CD_FRAMES * CD_SECS);
1043     	hsg %= CD_FRAMES * CD_SECS;
1044     	msf->sec = hsg / CD_FRAMES;
1045     	msf->frame = hsg % CD_FRAMES;
1046     
1047     	gscd_bin2bcd(&msf->min);	/* convert to BCD */
1048     	gscd_bin2bcd(&msf->sec);
1049     	gscd_bin2bcd(&msf->frame);
1050     }
1051     
1052     
1053     static void gscd_bin2bcd(unsigned char *p)
1054     {
1055     	int u, t;
1056     
1057     	u = *p % 10;
1058     	t = *p / 10;
1059     	*p = u | (t << 4);
1060     }
1061     
1062     
1063     #ifdef FUTURE_WORK
1064     static long gscd_msf2hsg(struct msf *mp)
1065     {
1066     	return gscd_bcd2bin(mp->frame)
1067     	    + gscd_bcd2bin(mp->sec) * CD_FRAMES
1068     	    + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
1069     }
1070     
1071     static int gscd_bcd2bin(unsigned char bcd)
1072     {
1073     	return (bcd >> 4) * 10 + (bcd & 0xF);
1074     }
1075     #endif
1076     
1077     MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
1078     MODULE_LICENSE("GPL");
1079     EXPORT_NO_SYMBOLS;
1080