1/*
2	pcd.c	(c) 1997-8  Grant R. Guenther <grant@torque.net>
3		            Under the terms of the GNU General Public License.
4
5	This is a high-level driver for parallel port ATAPI CD-ROM
6        drives based on chips supported by the paride module.
7
8        By default, the driver will autoprobe for a single parallel
9        port ATAPI CD-ROM drive, but if their individual parameters are
10        specified, the driver can handle up to 4 drives.
11
12        The behaviour of the pcd driver can be altered by setting
13        some parameters from the insmod command line.  The following
14        parameters are adjustable:
15
16            drive0      These four arguments can be arrays of
17            drive1      1-6 integers as follows:
18            drive2
19            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
20
21                        Where,
22
23                <prt>   is the base of the parallel port address for
24                        the corresponding drive.  (required)
25
26                <pro>   is the protocol number for the adapter that
27                        supports this drive.  These numbers are
28                        logged by 'paride' when the protocol modules
29                        are initialised.  (0 if not given)
30
31                <uni>   for those adapters that support chained
32                        devices, this is the unit selector for the
33                        chain of devices on the given port.  It should
34                        be zero for devices that don't support chaining.
35                        (0 if not given)
36
37                <mod>   this can be -1 to choose the best mode, or one
38                        of the mode numbers supported by the adapter.
39                        (-1 if not given)
40
41		<slv>   ATAPI CD-ROMs can be jumpered to master or slave.
42			Set this to 0 to choose the master drive, 1 to
43                        choose the slave, -1 (the default) to choose the
44			first drive found.
45
46                <dly>   some parallel ports require the driver to
47                        go more slowly.  -1 sets a default value that
48                        should work with the chosen protocol.  Otherwise,
49                        set this to a small integer, the larger it is
50                        the slower the port i/o.  In some cases, setting
51                        this to zero will speed up the device. (default -1)
52
53            major       You may use this parameter to overide the
54                        default major number (46) that this driver
55                        will use.  Be sure to change the device
56                        name as well.
57
58            name        This parameter is a character string that
59                        contains the name the kernel will use for this
60                        device (in /proc output, for instance).
61                        (default "pcd")
62
63            verbose     This parameter controls the amount of logging
64                        that the driver will do.  Set it to 0 for
65                        normal operation, 1 to see autoprobe progress
66                        messages, or 2 to see additional debugging
67                        output.  (default 0)
68
69            nice        This parameter controls the driver's use of
70                        idle CPU time, at the expense of some speed.
71
72	If this driver is built into the kernel, you can use kernel
73        the following command line parameters, with the same values
74        as the corresponding module parameters listed above:
75
76	    pcd.drive0
77	    pcd.drive1
78	    pcd.drive2
79	    pcd.drive3
80	    pcd.nice
81
82        In addition, you can use the parameter pcd.disable to disable
83        the driver entirely.
84
85*/
86
87/* Changes:
88
89	1.01	GRG 1998.01.24	Added test unit ready support
90	1.02    GRG 1998.05.06  Changes to pcd_completion, ready_wait,
91				and loosen interpretation of ATAPI
92			        standard for clearing error status.
93				Use spinlocks. Eliminate sti().
94	1.03    GRG 1998.06.16  Eliminated an Ugh
95	1.04	GRG 1998.08.15  Added extra debugging, improvements to
96				pcd_completion, use HZ in loop timing
97	1.05	GRG 1998.08.16	Conformed to "Uniform CD-ROM" standard
98	1.06    GRG 1998.08.19  Added audio ioctl support
99	1.07    GRG 1998.09.24  Increased reset timeout, added jumbo support
100
101*/
102
103#define	PCD_VERSION	"1.07"
104#define PCD_MAJOR	46
105#define PCD_NAME	"pcd"
106#define PCD_UNITS	4
107
108/* Here are things one can override from the insmod command.
109   Most are autoprobed by paride unless set here.  Verbose is off
110   by default.
111
112*/
113
114static int      verbose = 0;
115static int      major = PCD_MAJOR;
116static char     *name = PCD_NAME;
117static int      nice = 0;
118static int      disable = 0;
119
120static int drive0[6] = {0,0,0,-1,-1,-1};
121static int drive1[6] = {0,0,0,-1,-1,-1};
122static int drive2[6] = {0,0,0,-1,-1,-1};
123static int drive3[6] = {0,0,0,-1,-1,-1};
124
125static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
126static int pcd_drive_count;
127
128#define D_PRT   0
129#define D_PRO   1
130#define D_UNI   2
131#define D_MOD   3
132#define D_SLV   4
133#define D_DLY   5
134
135#define DU              (*drives[unit])
136
137/* end of parameters */
138
139#include <linux/module.h>
140#include <linux/errno.h>
141#include <linux/fs.h>
142#include <linux/kernel.h>
143#include <linux/delay.h>
144#include <linux/cdrom.h>
145#include <linux/spinlock.h>
146
147#include <asm/uaccess.h>
148
149#ifndef MODULE
150
151#include "setup.h"
152
153static STT pcd_stt[6] = {{"drive0",6,drive0},
154                         {"drive1",6,drive1},
155                         {"drive2",6,drive2},
156                         {"drive3",6,drive3},
157			 {"disable",1,&disable},
158                         {"nice",1,&nice}};
159
160void pcd_setup( char *str, int *ints)
161
162{       generic_setup(pcd_stt,6,str);
163}
164
165#endif
166
167MODULE_PARM(verbose,"i");
168MODULE_PARM(major,"i");
169MODULE_PARM(name,"s");
170MODULE_PARM(nice,"i");
171MODULE_PARM(drive0,"1-6i");
172MODULE_PARM(drive1,"1-6i");
173MODULE_PARM(drive2,"1-6i");
174MODULE_PARM(drive3,"1-6i");
175
176#include "paride.h"
177
178/* set up defines for blk.h,  why don't all drivers do it this way ? */
179
180#define MAJOR_NR	major
181#define DEVICE_NAME "PCD"
182#define DEVICE_REQUEST do_pcd_request
183#define DEVICE_NR(device) (MINOR(device))
184#define DEVICE_ON(device)
185#define DEVICE_OFF(device)
186
187#include <linux/blk.h>
188
189#include "pseudo.h"
190
191#define PCD_RETRIES	     5
192#define PCD_TMO		   800		/* timeout in jiffies */
193#define PCD_DELAY           50          /* spin delay in uS */
194#define PCD_READY_TMO	    20		/* in seconds */
195#define PCD_RESET_TMO	   100		/* in tenths of a second */
196
197#define PCD_SPIN	(1000000*PCD_TMO)/(HZ*PCD_DELAY)
198
199#define IDE_ERR		0x01
200#define IDE_DRQ         0x08
201#define IDE_READY       0x40
202#define IDE_BUSY        0x80
203
204int pcd_init(void);
205void cleanup_module( void );
206
207static int pcd_open(struct cdrom_device_info *cdi, int purpose);
208static void pcd_release(struct cdrom_device_info *cdi);
209static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
210static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
211static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
212static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
213static int pcd_drive_reset(struct cdrom_device_info *cdi);
214static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
215static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
216				unsigned int cmd, void *arg);
217static int pcd_packet(struct cdrom_device_info *cdi,
218				struct cdrom_generic_command *cgc);
219
220static int 	pcd_detect(void);
221static void 	pcd_probe_capabilities(void);
222static void     do_pcd_read_drq(void);
223static void 	do_pcd_request(request_queue_t * q);
224static void 	do_pcd_read(void);
225
226static int pcd_blocksizes[PCD_UNITS];
227
228struct pcd_unit {
229	struct pi_adapter pia;		/* interface to paride layer */
230	struct pi_adapter *pi;
231	int drive;			/* master/slave */
232	int last_sense;			/* result of last request sense */
233	int changed;			/* media change seen */
234	int present;			/* does this unit exist ? */
235	char *name;			/* pcd0, pcd1, etc */
236	struct cdrom_device_info info;	/* uniform cdrom interface */
237	};
238
239struct pcd_unit pcd[PCD_UNITS];
240
241/*  'unit' must be defined in all functions - either as a local or a param */
242
243#define PCD pcd[unit]
244#define PI PCD.pi
245
246static char pcd_scratch[64];
247static char pcd_buffer[2048];           /* raw block buffer */
248static int pcd_bufblk = -1;             /* block in buffer, in CD units,
249                                           -1 for nothing there. See also
250					   pd_unit.
251					 */
252
253/* the variables below are used mainly in the I/O request engine, which
254   processes only one request at a time.
255*/
256
257static int pcd_unit = -1;		/* unit of current request & bufblk */
258static int pcd_retries;			/* retries on current request */
259static int pcd_busy = 0;		/* request being processed ? */
260static int pcd_sector;			/* address of next requested sector */
261static int pcd_count;			/* number of blocks still to do */
262static char * pcd_buf;			/* buffer for request in progress */
263
264static int pcd_warned = 0;		/* Have we logged a phase warning ? */
265
266/* kernel glue structures */
267
268static struct block_device_operations pcd_bdops = {
269	owner:			THIS_MODULE,
270	open:			cdrom_open,
271	release:		cdrom_release,
272	ioctl:			cdrom_ioctl,
273	check_media_change:	cdrom_media_changed,
274};
275
276static struct cdrom_device_ops pcd_dops = {
277	pcd_open,
278	pcd_release,
279	pcd_drive_status,
280	pcd_media_changed,
281	pcd_tray_move,
282	pcd_lock_door,
283	0,			/* select speed */
284	0,			/* select disk  */
285	0, 			/* get last session */
286	pcd_get_mcn,
287	pcd_drive_reset,
288	pcd_audio_ioctl,
289	0,			/* dev_ioctl */
290	CDC_CLOSE_TRAY	   |
291	CDC_OPEN_TRAY	   |
292	CDC_LOCK	   |
293	CDC_MCN		   |
294	CDC_MEDIA_CHANGED  |
295	CDC_RESET	   |
296	CDC_PLAY_AUDIO	   |
297	CDC_GENERIC_PACKET |
298	CDC_CD_R	   |
299	CDC_CD_RW,
300	0,
301	pcd_packet,
302};
303
304static void pcd_init_units( void )
305
306{       int     unit, j;
307
308        pcd_drive_count = 0;
309        for (unit=0;unit<PCD_UNITS;unit++) {
310                PCD.pi = & PCD.pia;
311                PCD.present = 0;
312		PCD.last_sense = 0;
313		PCD.changed = 1;
314                PCD.drive = DU[D_SLV];
315                if (DU[D_PRT]) pcd_drive_count++;
316
317                j = 0;
318                while ((j < (sizeof(PCD.info.name)-2)) &&
319		       (PCD.info.name[j]=name[j])) j++;
320                PCD.info.name[j++] = '0' + unit;
321                PCD.info.name[j] = 0;
322		PCD.name = &PCD.info.name[0];
323
324		PCD.info.ops = &pcd_dops;
325		PCD.info.handle = NULL;
326		PCD.info.dev = MKDEV(major,unit);
327		PCD.info.speed = 0;
328		PCD.info.capacity = 1;
329		PCD.info.mask = 0;
330        }
331}
332
333int pcd_init (void)	/* preliminary initialisation */
334
335{       int 	i, unit;
336
337	if (disable) return -1;
338
339	pcd_init_units();
340
341	if (pcd_detect()) return -1;
342
343	/* get the atapi capabilities page */
344	pcd_probe_capabilities();
345
346	if (register_blkdev(MAJOR_NR,name,&pcd_bdops)) {
347		printk("pcd: unable to get major number %d\n",MAJOR_NR);
348		return -1;
349	}
350
351	for (unit=0;unit<PCD_UNITS;unit++) {
352		if (PCD.present) {
353			register_cdrom(&PCD.info);
354			devfs_plain_cdrom(&PCD.info, &pcd_bdops);
355		}
356	}
357
358	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
359	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read ahead */
360
361	for (i=0;i<PCD_UNITS;i++) pcd_blocksizes[i] = 1024;
362        blksize_size[MAJOR_NR] = pcd_blocksizes;
363
364	return 0;
365}
366
367static int pcd_open(struct cdrom_device_info *cdi, int purpose)
368
369{	int unit = DEVICE_NR(cdi->dev);
370
371	if  ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV;
372
373	return 0;
374}
375
376static void pcd_release(struct cdrom_device_info *cdi)
377
378{
379}
380
381#ifdef MODULE
382
383/* Glue for modules ... */
384
385int	init_module(void)
386
387{	int	err;
388
389#ifdef PARIDE_JUMBO
390       { extern paride_init();
391         paride_init();
392       }
393#endif
394
395	err = pcd_init();
396
397	return err;
398}
399
400void	cleanup_module(void)
401
402{	int unit;
403
404        for (unit=0;unit<PCD_UNITS;unit++)
405           if (PCD.present) {
406		pi_release(PI);
407		unregister_cdrom(&PCD.info);
408	   }
409
410	unregister_blkdev(MAJOR_NR,name);
411}
412
413#endif
414
415#define WR(c,r,v)       pi_write_regr(PI,c,r,v)
416#define RR(c,r)         (pi_read_regr(PI,c,r))
417
418static int pcd_wait( int unit, int go, int stop, char * fun, char * msg )
419
420{	int j, r, e, s, p;
421
422	j = 0;
423	while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PCD_SPIN))
424		udelay(PCD_DELAY);
425
426	if ((r&(IDE_ERR&stop))||(j>=PCD_SPIN)) {
427	   s = RR(0,7);
428	   e = RR(0,1);
429	   p = RR(0,2);
430       	   if (j >= PCD_SPIN) e |= 0x100;
431           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
432			   " loop=%d phase=%d\n",
433			    PCD.name,fun,msg,r,s,e,j,p);
434	   return (s<<8)+r;
435	}
436	return 0;
437}
438
439static int pcd_command( int unit, char * cmd, int dlen, char * fun )
440
441{	pi_connect(PI);
442
443        WR(0,6,0xa0 + 0x10*PCD.drive);
444
445	if (pcd_wait(unit,IDE_BUSY|IDE_DRQ,0,fun,"before command")) {
446		pi_disconnect(PI);
447		return -1;
448	}
449
450        WR(0,4,dlen % 256);
451        WR(0,5,dlen / 256);
452        WR(0,7,0xa0);          /* ATAPI packet command */
453
454        if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) {
455		pi_disconnect(PI);
456		return -1;
457	}
458
459        if (RR(0,2) != 1) {
460           printk("%s: %s: command phase error\n",PCD.name,fun);
461	   pi_disconnect(PI);
462           return -1;
463        }
464
465	pi_write_block(PI,cmd,12);
466
467	return 0;
468}
469
470static int pcd_completion( int unit, char * buf,  char * fun )
471
472{	int r, d, p, n, k, j;
473
474	r = -1; k = 0; j = 0;
475
476	if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
477						fun,"completion")) {
478	    r = 0;
479	    while (RR(0,7)&IDE_DRQ) {
480	        d = (RR(0,4)+256*RR(0,5));
481	        n = ((d+3)&0xfffc);
482	        p = RR(0,2)&3;
483
484	        if ((p == 2) && (n > 0) && (j == 0)) {
485		    pi_read_block(PI,buf,n);
486	            if (verbose > 1)
487			printk("%s: %s: Read %d bytes\n",PCD.name,fun,n);
488		    r = 0; j++;
489	        } else {
490		    if (verbose > 1)
491		        printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
492					PCD.name,fun,p,d,k);
493		    if ((verbose < 2) && !pcd_warned) {
494	               	pcd_warned = 1;
495			printk("%s: WARNING: ATAPI phase errors\n",PCD.name);
496			}
497		    mdelay(1);
498	        }
499		if (k++ > PCD_TMO) {
500			printk("%s: Stuck DRQ\n",PCD.name);
501			break;
502		}
503	        if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
504				fun,"completion")) {
505			r = -1;
506			break;
507		}
508	    }
509	}
510
511	pi_disconnect(PI);
512
513	return r;
514}
515
516static void pcd_req_sense( int unit, char *fun )
517
518{	char	rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
519	char	buf[16];
520	int 	r, c;
521
522	r = pcd_command(unit,rs_cmd,16,"Request sense");
523	mdelay(1);
524	if (!r) pcd_completion(unit,buf,"Request sense");
525
526	PCD.last_sense = -1;  c = 2;
527	if (!r) {
528            if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
529	                       PCD.name,fun,buf[2]&0xf,buf[12],buf[13]);
530	    c = buf[2]&0xf;
531	    PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16);
532        }
533	if ((c == 2) || (c == 6)) PCD.changed = 1;
534}
535
536static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
537
538{	int r;
539
540	r = pcd_command(unit,cmd,dlen,fun);
541	mdelay(1);
542	if (!r) r = pcd_completion(unit,buf,fun);
543	if (r) pcd_req_sense(unit,fun);
544
545	return r;
546}
547
548static int pcd_packet(struct cdrom_device_info *cdi,
549				struct cdrom_generic_command *cgc)
550{
551	char	*un_cmd;
552	int	unit = DEVICE_NR(cdi->dev);
553
554	un_cmd = cgc->cmd;
555	return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet");
556}
557
558#define DBMSG(msg)	((verbose>1)?(msg):NULL)
559
560static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
561
562{	int 	r;
563	int	unit = DEVICE_NR(cdi->dev);
564
565	r = PCD.changed;
566	PCD.changed = 0;
567
568	return r;
569}
570
571static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
572
573{	char	un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 };
574        int     unit = DEVICE_NR(cdi->dev);
575
576	return pcd_atapi(unit,un_cmd,0,pcd_scratch,
577				lock?"lock door":"unlock door");
578}
579
580static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
581
582{	char	ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 };
583	int	unit = DEVICE_NR(cdi->dev);
584
585	return pcd_atapi(unit,ej_cmd,0,pcd_scratch,
586				position?"eject":"close tray");
587}
588
589static void pcd_sleep( int cs )
590
591{       current->state = TASK_INTERRUPTIBLE;
592        schedule_timeout(cs);
593}
594
595static int pcd_reset( int unit )
596
597{	int	i, k, flg;
598	int	expect[5] = {1,1,1,0x14,0xeb};
599
600	pi_connect(PI);
601	WR(0,6,0xa0 + 0x10*PCD.drive);
602	WR(0,7,8);
603
604	pcd_sleep(20*HZ/1000);  		/* delay a bit */
605
606	k = 0;
607	while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY))
608		pcd_sleep(HZ/10);
609
610	flg = 1;
611	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
612
613	if (verbose) {
614		printk("%s: Reset (%d) signature = ",PCD.name,k);
615		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
616		if (!flg) printk(" (incorrect)");
617		printk("\n");
618	}
619
620	pi_disconnect(PI);
621	return flg-1;
622}
623
624static int pcd_drive_reset(struct cdrom_device_info *cdi)
625
626{	return pcd_reset(DEVICE_NR(cdi->dev));
627}
628
629static int pcd_ready_wait( int unit, int tmo )
630
631{       char    tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
632        int     k, p;
633
634        k = 0;
635        while (k < tmo) {
636          PCD.last_sense = 0;
637          pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
638          p = PCD.last_sense;
639          if (!p) return 0;
640	  if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
641          k++;
642          pcd_sleep(HZ);
643        }
644        return 0x000020;        /* timeout */
645}
646
647static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
648
649{	char    rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
650	int	unit = DEVICE_NR(cdi->dev);
651
652	if (pcd_ready_wait(unit,PCD_READY_TMO))
653		return CDS_DRIVE_NOT_READY;
654	if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")))
655		return CDS_NO_DISC;
656	return CDS_DISC_OK;
657}
658
659static int pcd_identify( int unit, char * id )
660
661{	int k, s;
662	char   id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
663
664	pcd_bufblk = -1;
665
666        s = pcd_atapi(unit,id_cmd,36,pcd_buffer,"identify");
667
668	if (s) return -1;
669	if ((pcd_buffer[0] & 0x1f) != 5) {
670	  if (verbose) printk("%s: %s is not a CD-ROM\n",
671			PCD.name,PCD.drive?"Slave":"Master");
672	  return -1;
673	}
674	for (k=0;k<16;k++) id[k] = pcd_buffer[16+k]; id[16] = 0;
675	k = 16; while ((k >= 0) && (id[k] <= 0x20)) { id[k] = 0; k--; }
676
677	printk("%s: %s: %s\n",PCD.name,PCD.drive?"Slave":"Master",id);
678
679	return 0;
680}
681
682static int pcd_probe( int unit, int ms, char * id )
683
684/*	returns  0, with id set if drive is detected
685	        -1, if drive detection failed
686*/
687
688{	if (ms == -1) {
689            for (PCD.drive=0;PCD.drive<=1;PCD.drive++)
690	       if (!pcd_reset(unit) && !pcd_identify(unit,id))
691		  return 0;
692	} else {
693	    PCD.drive = ms;
694            if (!pcd_reset(unit) && !pcd_identify(unit,id))
695		return 0;
696	}
697	return -1;
698}
699
700static void pcd_probe_capabilities( void )
701
702{	int	unit, r;
703	char	buffer[32];
704	char 	cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0};
705
706	for (unit=0;unit<PCD_UNITS;unit++) {
707		if (!PCD.present) continue;
708		r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities");
709		if (r) continue;
710		/* we should now have the cap page */
711		if ((buffer[11] & 1) == 0)
712			PCD.info.mask |= CDC_CD_R;
713		if ((buffer[11] & 2) == 0)
714			PCD.info.mask |= CDC_CD_RW;
715		if ((buffer[12] & 1) == 0)
716			PCD.info.mask |= CDC_PLAY_AUDIO;
717		if ((buffer[14] & 1) == 0)
718			PCD.info.mask |= CDC_LOCK;
719		if ((buffer[14] & 8) == 0)
720			PCD.info.mask |= CDC_OPEN_TRAY;
721		if ((buffer[14] >> 6) == 0)
722			PCD.info.mask |= CDC_CLOSE_TRAY;
723	}
724}
725
726static int pcd_detect( void )
727
728{	char    id[18];
729	int	k, unit;
730
731	printk("%s: %s version %s, major %d, nice %d\n",
732		name,name,PCD_VERSION,major,nice);
733
734	k = 0;
735	if (pcd_drive_count == 0) {  /* nothing spec'd - so autoprobe for 1 */
736	    unit = 0;
737	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pcd_buffer,
738                     PI_PCD,verbose,PCD.name)) {
739		if (!pcd_probe(unit,-1,id)) {
740			PCD.present = 1;
741			k++;
742		} else pi_release(PI);
743	    }
744
745	} else for (unit=0;unit<PCD_UNITS;unit++) if (DU[D_PRT])
746	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
747                        DU[D_PRO],DU[D_DLY],pcd_buffer,PI_PCD,verbose,
748                        PCD.name)) {
749		if (!pcd_probe(unit,DU[D_SLV],id)) {
750                        PCD.present = 1;
751                        k++;
752                } else pi_release(PI);
753            }
754
755	if (k) return 0;
756
757	printk("%s: No CD-ROM drive found\n",name);
758	return -1;
759}
760
761/* I/O request processing */
762
763static void do_pcd_request (request_queue_t * q)
764
765{       int unit;
766
767	if (pcd_busy) return;
768        while (1) {
769	    if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;
770	    INIT_REQUEST;
771	    if (CURRENT->cmd == READ) {
772		unit = MINOR(CURRENT->rq_dev);
773		if (unit != pcd_unit) {
774			pcd_bufblk = -1;
775			pcd_unit = unit;
776		}
777	        pcd_sector = CURRENT->sector;
778	        pcd_count = CURRENT->current_nr_sectors;
779	        pcd_buf = CURRENT->buffer;
780		pcd_busy = 1;
781	        ps_set_intr(do_pcd_read,0,0,nice);
782		return;
783	    }
784	    else end_request(0);
785	}
786}
787
788static int pcd_ready( void )
789
790{	int	unit = pcd_unit;
791
792	return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ;
793}
794
795static void pcd_transfer( void )
796
797{	int	k, o;
798
799	while (pcd_count && (pcd_sector/4 == pcd_bufblk)) {
800		o = (pcd_sector % 4) * 512;
801		for(k=0;k<512;k++) pcd_buf[k] = pcd_buffer[o+k];
802		pcd_count--;
803		pcd_buf += 512;
804		pcd_sector++;
805	}
806}
807
808static void pcd_start( void )
809
810{	int	unit = pcd_unit;
811	int	b, i;
812	char	rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
813	unsigned long    saved_flags;
814
815	pcd_bufblk = pcd_sector / 4;
816        b = pcd_bufblk;
817	for(i=0;i<4;i++) {
818	   rd_cmd[5-i] = b & 0xff;
819	   b = b >> 8;
820	}
821
822	if (pcd_command(unit,rd_cmd,2048,"read block")) {
823		pcd_bufblk = -1;
824		spin_lock_irqsave(&io_request_lock,saved_flags);
825		pcd_busy = 0;
826		end_request(0);
827		do_pcd_request(NULL);
828		spin_unlock_irqrestore(&io_request_lock,saved_flags);
829		return;
830	}
831
832	mdelay(1);
833
834	ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice);
835
836}
837
838static void do_pcd_read( void )
839
840
841{	int	unit = pcd_unit;
842	unsigned long    saved_flags;
843
844	pcd_busy = 1;
845	pcd_retries = 0;
846	pcd_transfer();
847	if (!pcd_count) {
848		spin_lock_irqsave(&io_request_lock,saved_flags);
849		end_request(1);
850		pcd_busy = 0;
851		do_pcd_request(NULL);
852		spin_unlock_irqrestore(&io_request_lock,saved_flags);
853		return;
854	}
855
856	pi_do_claimed(PI,pcd_start);
857}
858
859static void do_pcd_read_drq( void )
860
861{	int	unit = pcd_unit;
862	unsigned long    saved_flags;
863
864	if (pcd_completion(unit,pcd_buffer,"read block")) {
865                if (pcd_retries < PCD_RETRIES) {
866                        mdelay(1);
867                        pcd_retries++;
868			pi_do_claimed(PI,pcd_start);
869                        return;
870                        }
871		spin_lock_irqsave(&io_request_lock,saved_flags);
872		pcd_busy = 0;
873		pcd_bufblk = -1;
874		end_request(0);
875		do_pcd_request(NULL);
876		spin_unlock_irqrestore(&io_request_lock,saved_flags);
877		return;
878	}
879
880	do_pcd_read();
881	spin_lock_irqsave(&io_request_lock,saved_flags);
882	do_pcd_request(NULL);
883	spin_unlock_irqrestore(&io_request_lock,saved_flags);
884}
885
886/* the audio_ioctl stuff is adapted from sr_ioctl.c */
887
888static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
889                                unsigned int cmd, void *arg)
890
891{	int	unit = DEVICE_NR(cdi->dev);
892
893    	switch (cmd) {
894
895    	case CDROMREADTOCHDR:
896
897	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
898		struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
899		char buffer[32];
900		int r;
901
902		r = pcd_atapi(unit,cmd,12,buffer,"read toc header");
903
904		tochdr->cdth_trk0 = buffer[2];
905		tochdr->cdth_trk1 = buffer[3];
906
907		return r * EIO;
908    	}
909
910    	case CDROMREADTOCENTRY:
911
912    	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
913
914		struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
915		unsigned char buffer[32];
916		int	r;
917
918		cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
919		cmd[6] = tocentry->cdte_track;
920
921		r = pcd_atapi(unit,cmd,12,buffer,"read toc entry");
922
923        	tocentry->cdte_ctrl = buffer[5] & 0xf;
924        	tocentry->cdte_adr = buffer[5] >> 4;
925        	tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0;
926		if (tocentry->cdte_format == CDROM_MSF) {
927		    tocentry->cdte_addr.msf.minute = buffer[9];
928	    	    tocentry->cdte_addr.msf.second = buffer[10];
929	            tocentry->cdte_addr.msf.frame = buffer[11];
930	        } else
931	            tocentry->cdte_addr.lba =
932				(((((buffer[8] << 8) + buffer[9]) << 8)
933                                       + buffer[10]) << 8) + buffer[11];
934
935                return r * EIO;
936        }
937
938    	default:
939
940        	return -ENOSYS;
941    	}
942}
943
944static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
945
946{	char 	cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
947        char 	buffer[32];
948	int	k;
949	int	unit = DEVICE_NR(cdi->dev);
950
951        if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO;
952
953	for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9];
954	mcn->medium_catalog_number[13] = 0;
955
956	return 0;
957}
958
959/* end of pcd.c */
960
961MODULE_LICENSE("GPL");
962