• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/block/paride/
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
128enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
129
130/* end of parameters */
131
132#include <linux/module.h>
133#include <linux/init.h>
134#include <linux/errno.h>
135#include <linux/fs.h>
136#include <linux/kernel.h>
137#include <linux/delay.h>
138#include <linux/cdrom.h>
139#include <linux/spinlock.h>
140#include <linux/blkdev.h>
141#include <linux/smp_lock.h>
142#include <asm/uaccess.h>
143
144static DEFINE_SPINLOCK(pcd_lock);
145
146module_param(verbose, bool, 0644);
147module_param(major, int, 0);
148module_param(name, charp, 0);
149module_param(nice, int, 0);
150module_param_array(drive0, int, NULL, 0);
151module_param_array(drive1, int, NULL, 0);
152module_param_array(drive2, int, NULL, 0);
153module_param_array(drive3, int, NULL, 0);
154
155#include "paride.h"
156#include "pseudo.h"
157
158#define PCD_RETRIES	     5
159#define PCD_TMO		   800	/* timeout in jiffies */
160#define PCD_DELAY           50	/* spin delay in uS */
161#define PCD_READY_TMO	    20	/* in seconds */
162#define PCD_RESET_TMO	   100	/* in tenths of a second */
163
164#define PCD_SPIN	(1000000*PCD_TMO)/(HZ*PCD_DELAY)
165
166#define IDE_ERR		0x01
167#define IDE_DRQ         0x08
168#define IDE_READY       0x40
169#define IDE_BUSY        0x80
170
171static int pcd_open(struct cdrom_device_info *cdi, int purpose);
172static void pcd_release(struct cdrom_device_info *cdi);
173static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
174static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
175static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
176static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
177static int pcd_drive_reset(struct cdrom_device_info *cdi);
178static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
179static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
180			   unsigned int cmd, void *arg);
181static int pcd_packet(struct cdrom_device_info *cdi,
182		      struct packet_command *cgc);
183
184static int pcd_detect(void);
185static void pcd_probe_capabilities(void);
186static void do_pcd_read_drq(void);
187static void do_pcd_request(struct request_queue * q);
188static void do_pcd_read(void);
189
190struct pcd_unit {
191	struct pi_adapter pia;	/* interface to paride layer */
192	struct pi_adapter *pi;
193	int drive;		/* master/slave */
194	int last_sense;		/* result of last request sense */
195	int changed;		/* media change seen */
196	int present;		/* does this unit exist ? */
197	char *name;		/* pcd0, pcd1, etc */
198	struct cdrom_device_info info;	/* uniform cdrom interface */
199	struct gendisk *disk;
200};
201
202static struct pcd_unit pcd[PCD_UNITS];
203
204static char pcd_scratch[64];
205static char pcd_buffer[2048];	/* raw block buffer */
206static int pcd_bufblk = -1;	/* block in buffer, in CD units,
207				   -1 for nothing there. See also
208				   pd_unit.
209				 */
210
211/* the variables below are used mainly in the I/O request engine, which
212   processes only one request at a time.
213*/
214
215static struct pcd_unit *pcd_current; /* current request's drive */
216static struct request *pcd_req;
217static int pcd_retries;		/* retries on current request */
218static int pcd_busy;		/* request being processed ? */
219static int pcd_sector;		/* address of next requested sector */
220static int pcd_count;		/* number of blocks still to do */
221static char *pcd_buf;		/* buffer for request in progress */
222
223/* kernel glue structures */
224
225static int pcd_block_open(struct block_device *bdev, fmode_t mode)
226{
227	struct pcd_unit *cd = bdev->bd_disk->private_data;
228	int ret;
229
230	lock_kernel();
231	ret = cdrom_open(&cd->info, bdev, mode);
232	unlock_kernel();
233
234	return ret;
235}
236
237static int pcd_block_release(struct gendisk *disk, fmode_t mode)
238{
239	struct pcd_unit *cd = disk->private_data;
240	lock_kernel();
241	cdrom_release(&cd->info, mode);
242	unlock_kernel();
243	return 0;
244}
245
246static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
247				unsigned cmd, unsigned long arg)
248{
249	struct pcd_unit *cd = bdev->bd_disk->private_data;
250	int ret;
251
252	lock_kernel();
253	ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
254	unlock_kernel();
255
256	return ret;
257}
258
259static int pcd_block_media_changed(struct gendisk *disk)
260{
261	struct pcd_unit *cd = disk->private_data;
262	return cdrom_media_changed(&cd->info);
263}
264
265static const struct block_device_operations pcd_bdops = {
266	.owner		= THIS_MODULE,
267	.open		= pcd_block_open,
268	.release	= pcd_block_release,
269	.ioctl		= pcd_block_ioctl,
270	.media_changed	= pcd_block_media_changed,
271};
272
273static struct cdrom_device_ops pcd_dops = {
274	.open		= pcd_open,
275	.release	= pcd_release,
276	.drive_status	= pcd_drive_status,
277	.media_changed	= pcd_media_changed,
278	.tray_move	= pcd_tray_move,
279	.lock_door	= pcd_lock_door,
280	.get_mcn	= pcd_get_mcn,
281	.reset		= pcd_drive_reset,
282	.audio_ioctl	= pcd_audio_ioctl,
283	.generic_packet	= pcd_packet,
284	.capability	= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
285			  CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
286			  CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
287			  CDC_CD_RW,
288};
289
290static void pcd_init_units(void)
291{
292	struct pcd_unit *cd;
293	int unit;
294
295	pcd_drive_count = 0;
296	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
297		struct gendisk *disk = alloc_disk(1);
298		if (!disk)
299			continue;
300		cd->disk = disk;
301		cd->pi = &cd->pia;
302		cd->present = 0;
303		cd->last_sense = 0;
304		cd->changed = 1;
305		cd->drive = (*drives[unit])[D_SLV];
306		if ((*drives[unit])[D_PRT])
307			pcd_drive_count++;
308
309		cd->name = &cd->info.name[0];
310		snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
311		cd->info.ops = &pcd_dops;
312		cd->info.handle = cd;
313		cd->info.speed = 0;
314		cd->info.capacity = 1;
315		cd->info.mask = 0;
316		disk->major = major;
317		disk->first_minor = unit;
318		strcpy(disk->disk_name, cd->name);	/* umm... */
319		disk->fops = &pcd_bdops;
320	}
321}
322
323static int pcd_open(struct cdrom_device_info *cdi, int purpose)
324{
325	struct pcd_unit *cd = cdi->handle;
326	if (!cd->present)
327		return -ENODEV;
328	return 0;
329}
330
331static void pcd_release(struct cdrom_device_info *cdi)
332{
333}
334
335static inline int status_reg(struct pcd_unit *cd)
336{
337	return pi_read_regr(cd->pi, 1, 6);
338}
339
340static inline int read_reg(struct pcd_unit *cd, int reg)
341{
342	return pi_read_regr(cd->pi, 0, reg);
343}
344
345static inline void write_reg(struct pcd_unit *cd, int reg, int val)
346{
347	pi_write_regr(cd->pi, 0, reg, val);
348}
349
350static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
351{
352	int j, r, e, s, p;
353
354	j = 0;
355	while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
356	       && (j++ < PCD_SPIN))
357		udelay(PCD_DELAY);
358
359	if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
360		s = read_reg(cd, 7);
361		e = read_reg(cd, 1);
362		p = read_reg(cd, 2);
363		if (j > PCD_SPIN)
364			e |= 0x100;
365		if (fun)
366			printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
367			       " loop=%d phase=%d\n",
368			       cd->name, fun, msg, r, s, e, j, p);
369		return (s << 8) + r;
370	}
371	return 0;
372}
373
374static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
375{
376	pi_connect(cd->pi);
377
378	write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
379
380	if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
381		pi_disconnect(cd->pi);
382		return -1;
383	}
384
385	write_reg(cd, 4, dlen % 256);
386	write_reg(cd, 5, dlen / 256);
387	write_reg(cd, 7, 0xa0);	/* ATAPI packet command */
388
389	if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
390		pi_disconnect(cd->pi);
391		return -1;
392	}
393
394	if (read_reg(cd, 2) != 1) {
395		printk("%s: %s: command phase error\n", cd->name, fun);
396		pi_disconnect(cd->pi);
397		return -1;
398	}
399
400	pi_write_block(cd->pi, cmd, 12);
401
402	return 0;
403}
404
405static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
406{
407	int r, d, p, n, k, j;
408
409	r = -1;
410	k = 0;
411	j = 0;
412
413	if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
414		      fun, "completion")) {
415		r = 0;
416		while (read_reg(cd, 7) & IDE_DRQ) {
417			d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
418			n = (d + 3) & 0xfffc;
419			p = read_reg(cd, 2) & 3;
420
421			if ((p == 2) && (n > 0) && (j == 0)) {
422				pi_read_block(cd->pi, buf, n);
423				if (verbose > 1)
424					printk("%s: %s: Read %d bytes\n",
425					       cd->name, fun, n);
426				r = 0;
427				j++;
428			} else {
429				if (verbose > 1)
430					printk
431					    ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
432					     cd->name, fun, p, d, k);
433				if (verbose < 2)
434					printk_once(
435					    "%s: WARNING: ATAPI phase errors\n",
436					    cd->name);
437				mdelay(1);
438			}
439			if (k++ > PCD_TMO) {
440				printk("%s: Stuck DRQ\n", cd->name);
441				break;
442			}
443			if (pcd_wait
444			    (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
445			     "completion")) {
446				r = -1;
447				break;
448			}
449		}
450	}
451
452	pi_disconnect(cd->pi);
453
454	return r;
455}
456
457static void pcd_req_sense(struct pcd_unit *cd, char *fun)
458{
459	char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
460	char buf[16];
461	int r, c;
462
463	r = pcd_command(cd, rs_cmd, 16, "Request sense");
464	mdelay(1);
465	if (!r)
466		pcd_completion(cd, buf, "Request sense");
467
468	cd->last_sense = -1;
469	c = 2;
470	if (!r) {
471		if (fun)
472			printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
473			       cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
474		c = buf[2] & 0xf;
475		cd->last_sense =
476		    c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
477	}
478	if ((c == 2) || (c == 6))
479		cd->changed = 1;
480}
481
482static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
483{
484	int r;
485
486	r = pcd_command(cd, cmd, dlen, fun);
487	mdelay(1);
488	if (!r)
489		r = pcd_completion(cd, buf, fun);
490	if (r)
491		pcd_req_sense(cd, fun);
492
493	return r;
494}
495
496static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
497{
498	return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
499			 "generic packet");
500}
501
502#define DBMSG(msg)	((verbose>1)?(msg):NULL)
503
504static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
505{
506	struct pcd_unit *cd = cdi->handle;
507	int res = cd->changed;
508	if (res)
509		cd->changed = 0;
510	return res;
511}
512
513static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
514{
515	char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
516
517	return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
518			 lock ? "lock door" : "unlock door");
519}
520
521static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
522{
523	char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
524
525	return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
526			 position ? "eject" : "close tray");
527}
528
529static void pcd_sleep(int cs)
530{
531	schedule_timeout_interruptible(cs);
532}
533
534static int pcd_reset(struct pcd_unit *cd)
535{
536	int i, k, flg;
537	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
538
539	pi_connect(cd->pi);
540	write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
541	write_reg(cd, 7, 8);
542
543	pcd_sleep(20 * HZ / 1000);	/* delay a bit */
544
545	k = 0;
546	while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
547		pcd_sleep(HZ / 10);
548
549	flg = 1;
550	for (i = 0; i < 5; i++)
551		flg &= (read_reg(cd, i + 1) == expect[i]);
552
553	if (verbose) {
554		printk("%s: Reset (%d) signature = ", cd->name, k);
555		for (i = 0; i < 5; i++)
556			printk("%3x", read_reg(cd, i + 1));
557		if (!flg)
558			printk(" (incorrect)");
559		printk("\n");
560	}
561
562	pi_disconnect(cd->pi);
563	return flg - 1;
564}
565
566static int pcd_drive_reset(struct cdrom_device_info *cdi)
567{
568	return pcd_reset(cdi->handle);
569}
570
571static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
572{
573	char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
574	int k, p;
575
576	k = 0;
577	while (k < tmo) {
578		cd->last_sense = 0;
579		pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
580		p = cd->last_sense;
581		if (!p)
582			return 0;
583		if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
584			return p;
585		k++;
586		pcd_sleep(HZ);
587	}
588	return 0x000020;	/* timeout */
589}
590
591static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
592{
593	char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
594	struct pcd_unit *cd = cdi->handle;
595
596	if (pcd_ready_wait(cd, PCD_READY_TMO))
597		return CDS_DRIVE_NOT_READY;
598	if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
599		return CDS_NO_DISC;
600	return CDS_DISC_OK;
601}
602
603static int pcd_identify(struct pcd_unit *cd, char *id)
604{
605	int k, s;
606	char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
607
608	pcd_bufblk = -1;
609
610	s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
611
612	if (s)
613		return -1;
614	if ((pcd_buffer[0] & 0x1f) != 5) {
615		if (verbose)
616			printk("%s: %s is not a CD-ROM\n",
617			       cd->name, cd->drive ? "Slave" : "Master");
618		return -1;
619	}
620	memcpy(id, pcd_buffer + 16, 16);
621	id[16] = 0;
622	k = 16;
623	while ((k >= 0) && (id[k] <= 0x20)) {
624		id[k] = 0;
625		k--;
626	}
627
628	printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
629
630	return 0;
631}
632
633/*
634 * returns  0, with id set if drive is detected
635 *	    -1, if drive detection failed
636 */
637static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
638{
639	if (ms == -1) {
640		for (cd->drive = 0; cd->drive <= 1; cd->drive++)
641			if (!pcd_reset(cd) && !pcd_identify(cd, id))
642				return 0;
643	} else {
644		cd->drive = ms;
645		if (!pcd_reset(cd) && !pcd_identify(cd, id))
646			return 0;
647	}
648	return -1;
649}
650
651static void pcd_probe_capabilities(void)
652{
653	int unit, r;
654	char buffer[32];
655	char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
656	struct pcd_unit *cd;
657
658	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
659		if (!cd->present)
660			continue;
661		r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
662		if (r)
663			continue;
664		/* we should now have the cap page */
665		if ((buffer[11] & 1) == 0)
666			cd->info.mask |= CDC_CD_R;
667		if ((buffer[11] & 2) == 0)
668			cd->info.mask |= CDC_CD_RW;
669		if ((buffer[12] & 1) == 0)
670			cd->info.mask |= CDC_PLAY_AUDIO;
671		if ((buffer[14] & 1) == 0)
672			cd->info.mask |= CDC_LOCK;
673		if ((buffer[14] & 8) == 0)
674			cd->info.mask |= CDC_OPEN_TRAY;
675		if ((buffer[14] >> 6) == 0)
676			cd->info.mask |= CDC_CLOSE_TRAY;
677	}
678}
679
680static int pcd_detect(void)
681{
682	char id[18];
683	int k, unit;
684	struct pcd_unit *cd;
685
686	printk("%s: %s version %s, major %d, nice %d\n",
687	       name, name, PCD_VERSION, major, nice);
688
689	k = 0;
690	if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
691		cd = pcd;
692		if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
693			    PI_PCD, verbose, cd->name)) {
694			if (!pcd_probe(cd, -1, id) && cd->disk) {
695				cd->present = 1;
696				k++;
697			} else
698				pi_release(cd->pi);
699		}
700	} else {
701		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
702			int *conf = *drives[unit];
703			if (!conf[D_PRT])
704				continue;
705			if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
706				     conf[D_UNI], conf[D_PRO], conf[D_DLY],
707				     pcd_buffer, PI_PCD, verbose, cd->name))
708				continue;
709			if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
710				cd->present = 1;
711				k++;
712			} else
713				pi_release(cd->pi);
714		}
715	}
716	if (k)
717		return 0;
718
719	printk("%s: No CD-ROM drive found\n", name);
720	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
721		put_disk(cd->disk);
722	return -1;
723}
724
725/* I/O request processing */
726static struct request_queue *pcd_queue;
727
728static void do_pcd_request(struct request_queue * q)
729{
730	if (pcd_busy)
731		return;
732	while (1) {
733		if (!pcd_req) {
734			pcd_req = blk_fetch_request(q);
735			if (!pcd_req)
736				return;
737		}
738
739		if (rq_data_dir(pcd_req) == READ) {
740			struct pcd_unit *cd = pcd_req->rq_disk->private_data;
741			if (cd != pcd_current)
742				pcd_bufblk = -1;
743			pcd_current = cd;
744			pcd_sector = blk_rq_pos(pcd_req);
745			pcd_count = blk_rq_cur_sectors(pcd_req);
746			pcd_buf = pcd_req->buffer;
747			pcd_busy = 1;
748			ps_set_intr(do_pcd_read, NULL, 0, nice);
749			return;
750		} else {
751			__blk_end_request_all(pcd_req, -EIO);
752			pcd_req = NULL;
753		}
754	}
755}
756
757static inline void next_request(int err)
758{
759	unsigned long saved_flags;
760
761	spin_lock_irqsave(&pcd_lock, saved_flags);
762	if (!__blk_end_request_cur(pcd_req, err))
763		pcd_req = NULL;
764	pcd_busy = 0;
765	do_pcd_request(pcd_queue);
766	spin_unlock_irqrestore(&pcd_lock, saved_flags);
767}
768
769static int pcd_ready(void)
770{
771	return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
772}
773
774static void pcd_transfer(void)
775{
776
777	while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
778		int o = (pcd_sector % 4) * 512;
779		memcpy(pcd_buf, pcd_buffer + o, 512);
780		pcd_count--;
781		pcd_buf += 512;
782		pcd_sector++;
783	}
784}
785
786static void pcd_start(void)
787{
788	int b, i;
789	char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
790
791	pcd_bufblk = pcd_sector / 4;
792	b = pcd_bufblk;
793	for (i = 0; i < 4; i++) {
794		rd_cmd[5 - i] = b & 0xff;
795		b = b >> 8;
796	}
797
798	if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
799		pcd_bufblk = -1;
800		next_request(-EIO);
801		return;
802	}
803
804	mdelay(1);
805
806	ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
807}
808
809static void do_pcd_read(void)
810{
811	pcd_busy = 1;
812	pcd_retries = 0;
813	pcd_transfer();
814	if (!pcd_count) {
815		next_request(0);
816		return;
817	}
818
819	pi_do_claimed(pcd_current->pi, pcd_start);
820}
821
822static void do_pcd_read_drq(void)
823{
824	unsigned long saved_flags;
825
826	if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
827		if (pcd_retries < PCD_RETRIES) {
828			mdelay(1);
829			pcd_retries++;
830			pi_do_claimed(pcd_current->pi, pcd_start);
831			return;
832		}
833		pcd_bufblk = -1;
834		next_request(-EIO);
835		return;
836	}
837
838	do_pcd_read();
839	spin_lock_irqsave(&pcd_lock, saved_flags);
840	do_pcd_request(pcd_queue);
841	spin_unlock_irqrestore(&pcd_lock, saved_flags);
842}
843
844/* the audio_ioctl stuff is adapted from sr_ioctl.c */
845
846static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
847{
848	struct pcd_unit *cd = cdi->handle;
849
850	switch (cmd) {
851
852	case CDROMREADTOCHDR:
853
854		{
855			char cmd[12] =
856			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
857			 0, 0, 0 };
858			struct cdrom_tochdr *tochdr =
859			    (struct cdrom_tochdr *) arg;
860			char buffer[32];
861			int r;
862
863			r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
864
865			tochdr->cdth_trk0 = buffer[2];
866			tochdr->cdth_trk1 = buffer[3];
867
868			return r ? -EIO : 0;
869		}
870
871	case CDROMREADTOCENTRY:
872
873		{
874			char cmd[12] =
875			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
876			 0, 0, 0 };
877
878			struct cdrom_tocentry *tocentry =
879			    (struct cdrom_tocentry *) arg;
880			unsigned char buffer[32];
881			int r;
882
883			cmd[1] =
884			    (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
885			cmd[6] = tocentry->cdte_track;
886
887			r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
888
889			tocentry->cdte_ctrl = buffer[5] & 0xf;
890			tocentry->cdte_adr = buffer[5] >> 4;
891			tocentry->cdte_datamode =
892			    (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
893			if (tocentry->cdte_format == CDROM_MSF) {
894				tocentry->cdte_addr.msf.minute = buffer[9];
895				tocentry->cdte_addr.msf.second = buffer[10];
896				tocentry->cdte_addr.msf.frame = buffer[11];
897			} else
898				tocentry->cdte_addr.lba =
899				    (((((buffer[8] << 8) + buffer[9]) << 8)
900				      + buffer[10]) << 8) + buffer[11];
901
902			return r ? -EIO : 0;
903		}
904
905	default:
906
907		return -ENOSYS;
908	}
909}
910
911static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
912{
913	char cmd[12] =
914	    { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
915	char buffer[32];
916
917	if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
918		return -EIO;
919
920	memcpy(mcn->medium_catalog_number, buffer + 9, 13);
921	mcn->medium_catalog_number[13] = 0;
922
923	return 0;
924}
925
926static int __init pcd_init(void)
927{
928	struct pcd_unit *cd;
929	int unit;
930
931	if (disable)
932		return -EINVAL;
933
934	pcd_init_units();
935
936	if (pcd_detect())
937		return -ENODEV;
938
939	/* get the atapi capabilities page */
940	pcd_probe_capabilities();
941
942	if (register_blkdev(major, name)) {
943		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
944			put_disk(cd->disk);
945		return -EBUSY;
946	}
947
948	pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
949	if (!pcd_queue) {
950		unregister_blkdev(major, name);
951		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
952			put_disk(cd->disk);
953		return -ENOMEM;
954	}
955
956	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
957		if (cd->present) {
958			register_cdrom(&cd->info);
959			cd->disk->private_data = cd;
960			cd->disk->queue = pcd_queue;
961			add_disk(cd->disk);
962		}
963	}
964
965	return 0;
966}
967
968static void __exit pcd_exit(void)
969{
970	struct pcd_unit *cd;
971	int unit;
972
973	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
974		if (cd->present) {
975			del_gendisk(cd->disk);
976			pi_release(cd->pi);
977			unregister_cdrom(&cd->info);
978		}
979		put_disk(cd->disk);
980	}
981	blk_cleanup_queue(pcd_queue);
982	unregister_blkdev(major, name);
983}
984
985MODULE_LICENSE("GPL");
986module_init(pcd_init)
987module_exit(pcd_exit)
988