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