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 
114 static int      verbose = 0;
115 static int      major = PCD_MAJOR;
116 static char     *name = PCD_NAME;
117 static int      nice = 0;
118 static int      disable = 0;
119 
120 static int drive0[6] = {0,0,0,-1,-1,-1};
121 static int drive1[6] = {0,0,0,-1,-1,-1};
122 static int drive2[6] = {0,0,0,-1,-1,-1};
123 static int drive3[6] = {0,0,0,-1,-1,-1};
124 
125 static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
126 static 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 
153 static 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 
pcd_setup(char * str,int * ints)160 void pcd_setup( char *str, int *ints)
161 
162 {       generic_setup(pcd_stt,6,str);
163 }
164 
165 #endif
166 
167 MODULE_PARM(verbose,"i");
168 MODULE_PARM(major,"i");
169 MODULE_PARM(name,"s");
170 MODULE_PARM(nice,"i");
171 MODULE_PARM(drive0,"1-6i");
172 MODULE_PARM(drive1,"1-6i");
173 MODULE_PARM(drive2,"1-6i");
174 MODULE_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 
204 int pcd_init(void);
205 void cleanup_module( void );
206 
207 static int pcd_open(struct cdrom_device_info *cdi, int purpose);
208 static void pcd_release(struct cdrom_device_info *cdi);
209 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
210 static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
211 static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
212 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
213 static int pcd_drive_reset(struct cdrom_device_info *cdi);
214 static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
215 static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
216 				unsigned int cmd, void *arg);
217 static int pcd_packet(struct cdrom_device_info *cdi,
218 				struct cdrom_generic_command *cgc);
219 
220 static int 	pcd_detect(void);
221 static void 	pcd_probe_capabilities(void);
222 static void     do_pcd_read_drq(void);
223 static void 	do_pcd_request(request_queue_t * q);
224 static void 	do_pcd_read(void);
225 
226 static int pcd_blocksizes[PCD_UNITS];
227 
228 struct 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 
239 struct 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 
246 static char pcd_scratch[64];
247 static char pcd_buffer[2048];           /* raw block buffer */
248 static 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 
257 static int pcd_unit = -1;		/* unit of current request & bufblk */
258 static int pcd_retries;			/* retries on current request */
259 static int pcd_busy = 0;		/* request being processed ? */
260 static int pcd_sector;			/* address of next requested sector */
261 static int pcd_count;			/* number of blocks still to do */
262 static char * pcd_buf;			/* buffer for request in progress */
263 
264 static int pcd_warned = 0;		/* Have we logged a phase warning ? */
265 
266 /* kernel glue structures */
267 
268 static 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 
276 static 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 
pcd_init_units(void)304 static 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 
pcd_init(void)333 int 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 
pcd_open(struct cdrom_device_info * cdi,int purpose)367 static 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 
pcd_release(struct cdrom_device_info * cdi)376 static void pcd_release(struct cdrom_device_info *cdi)
377 
378 {
379 }
380 
381 #ifdef MODULE
382 
383 /* Glue for modules ... */
384 
init_module(void)385 int	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 
cleanup_module(void)400 void	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 
pcd_wait(int unit,int go,int stop,char * fun,char * msg)418 static 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 
pcd_command(int unit,char * cmd,int dlen,char * fun)439 static 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 
pcd_completion(int unit,char * buf,char * fun)470 static 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 
pcd_req_sense(int unit,char * fun)516 static 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 
pcd_atapi(int unit,char * cmd,int dlen,char * buf,char * fun)536 static 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 
pcd_packet(struct cdrom_device_info * cdi,struct cdrom_generic_command * cgc)548 static 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 
pcd_media_changed(struct cdrom_device_info * cdi,int slot_nr)560 static 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 
pcd_lock_door(struct cdrom_device_info * cdi,int lock)571 static 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 
pcd_tray_move(struct cdrom_device_info * cdi,int position)580 static 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 
pcd_sleep(int cs)589 static void pcd_sleep( int cs )
590 
591 {       current->state = TASK_INTERRUPTIBLE;
592         schedule_timeout(cs);
593 }
594 
pcd_reset(int unit)595 static 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 
pcd_drive_reset(struct cdrom_device_info * cdi)624 static int pcd_drive_reset(struct cdrom_device_info *cdi)
625 
626 {	return pcd_reset(DEVICE_NR(cdi->dev));
627 }
628 
pcd_ready_wait(int unit,int tmo)629 static 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 
pcd_drive_status(struct cdrom_device_info * cdi,int slot_nr)647 static 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 
pcd_identify(int unit,char * id)659 static 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 
pcd_probe(int unit,int ms,char * id)682 static 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 
pcd_probe_capabilities(void)700 static 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 
pcd_detect(void)726 static 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 
do_pcd_request(request_queue_t * q)763 static 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 
pcd_ready(void)788 static int pcd_ready( void )
789 
790 {	int	unit = pcd_unit;
791 
792 	return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ;
793 }
794 
pcd_transfer(void)795 static 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 
pcd_start(void)808 static 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 
do_pcd_read(void)838 static 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 
do_pcd_read_drq(void)859 static 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 
pcd_audio_ioctl(struct cdrom_device_info * cdi,unsigned int cmd,void * arg)888 static 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 
pcd_get_mcn(struct cdrom_device_info * cdi,struct cdrom_mcn * mcn)944 static 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 
961 MODULE_LICENSE("GPL");
962