Import 2.3.18pre1
[davej-history.git] / drivers / block / paride / pcd.c
blob13b5f1b6a82a1b6a644de2d0f0f66ad244901128
1 /*
2 pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU public license.
5 This is a high-level driver for parallel port ATAPI CD-ROM
6 drives based on chips supported by the paride module.
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.
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:
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>
21 Where,
23 <prt> is the base of the parallel port address for
24 the corresponding drive. (required)
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)
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)
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)
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.
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)
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.
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")
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)
69 nice This parameter controls the driver's use of
70 idle CPU time, at the expense of some speed.
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:
76 pcd.drive0
77 pcd.drive1
78 pcd.drive2
79 pcd.drive3
80 pcd.nice
82 In addition, you can use the parameter pcd.disable to disable
83 the driver entirely.
87 /* Changes:
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
103 #define PCD_VERSION "1.07"
104 #define PCD_MAJOR 46
105 #define PCD_NAME "pcd"
106 #define PCD_UNITS 4
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.
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;
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};
125 static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
126 static int pcd_drive_count;
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
135 #define DU (*drives[unit])
137 /* end of parameters */
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>
147 #include <asm/uaccess.h>
149 #ifndef MODULE
151 #include "setup.h"
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}};
160 void pcd_setup( char *str, int *ints)
162 { generic_setup(pcd_stt,6,str);
165 #endif
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");
176 #include "paride.h"
178 /* set up defines for blk.h, why don't all drivers do it this way ? */
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)
187 #include <linux/blk.h>
189 #include "pseudo.h"
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 */
197 #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
199 #define IDE_ERR 0x01
200 #define IDE_DRQ 0x08
201 #define IDE_READY 0x40
202 #define IDE_BUSY 0x80
204 int pcd_init(void);
205 void cleanup_module( void );
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);
218 static int pcd_detect(void);
219 static void do_pcd_read_drq(void);
220 static void do_pcd_request(void);
221 static void do_pcd_read(void);
223 static int pcd_blocksizes[PCD_UNITS];
225 struct pcd_unit {
226 struct pi_adapter pia; /* interface to paride layer */
227 struct pi_adapter *pi;
228 int drive; /* master/slave */
229 int last_sense; /* result of last request sense */
230 int changed; /* media change seen */
231 int present; /* does this unit exist ? */
232 char *name; /* pcd0, pcd1, etc */
233 struct cdrom_device_info info; /* uniform cdrom interface */
236 struct pcd_unit pcd[PCD_UNITS];
238 /* 'unit' must be defined in all functions - either as a local or a param */
240 #define PCD pcd[unit]
241 #define PI PCD.pi
243 static char pcd_scratch[64];
244 static char pcd_buffer[2048]; /* raw block buffer */
245 static int pcd_bufblk = -1; /* block in buffer, in CD units,
246 -1 for nothing there. See also
247 pd_unit.
250 /* the variables below are used mainly in the I/O request engine, which
251 processes only one request at a time.
254 static int pcd_unit = -1; /* unit of current request & bufblk */
255 static int pcd_retries; /* retries on current request */
256 static int pcd_busy = 0; /* request being processed ? */
257 static int pcd_sector; /* address of next requested sector */
258 static int pcd_count; /* number of blocks still to do */
259 static char * pcd_buf; /* buffer for request in progress */
261 static int pcd_warned = 0; /* Have we logged a phase warning ? */
263 /* kernel glue structures */
265 static struct cdrom_device_ops pcd_dops = {
266 pcd_open,
267 pcd_release,
268 pcd_drive_status,
269 pcd_media_changed,
270 pcd_tray_move,
271 pcd_lock_door,
272 0, /* select speed */
273 0, /* select disk */
274 0, /* get last session */
275 pcd_get_mcn,
276 pcd_drive_reset,
277 pcd_audio_ioctl,
278 0, /* dev_ioctl */
279 CDC_CLOSE_TRAY |
280 CDC_OPEN_TRAY |
281 CDC_LOCK |
282 CDC_MCN |
283 CDC_MEDIA_CHANGED |
284 CDC_RESET |
285 CDC_PLAY_AUDIO,
289 static void pcd_init_units( void )
291 { int unit, j;
293 pcd_drive_count = 0;
294 for (unit=0;unit<PCD_UNITS;unit++) {
295 PCD.pi = & PCD.pia;
296 PCD.present = 0;
297 PCD.last_sense = 0;
298 PCD.changed = 1;
299 PCD.drive = DU[D_SLV];
300 if (DU[D_PRT]) pcd_drive_count++;
302 j = 0;
303 while ((j < (sizeof(PCD.info.name)-2)) &&
304 (PCD.info.name[j]=name[j])) j++;
305 PCD.info.name[j++] = '0' + unit;
306 PCD.info.name[j] = 0;
307 PCD.name = &PCD.info.name[0];
309 PCD.info.ops = &pcd_dops;
310 PCD.info.handle = NULL;
311 PCD.info.dev = MKDEV(major,unit);
312 PCD.info.speed = 0;
313 PCD.info.capacity = 1;
314 PCD.info.mask = 0;
318 int pcd_init (void) /* preliminary initialisation */
320 { int i, unit;
322 if (disable) return -1;
324 pcd_init_units();
326 if (pcd_detect()) return -1;
328 if (register_blkdev(MAJOR_NR,name,&cdrom_fops)) {
329 printk("pcd: unable to get major number %d\n",MAJOR_NR);
330 return -1;
333 for (unit=0;unit<PCD_UNITS;unit++)
334 if (PCD.present) register_cdrom(&PCD.info);
336 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
337 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
339 for (i=0;i<PCD_UNITS;i++) pcd_blocksizes[i] = 1024;
340 blksize_size[MAJOR_NR] = pcd_blocksizes;
342 return 0;
345 static int pcd_open(struct cdrom_device_info *cdi, int purpose)
347 { int unit = DEVICE_NR(cdi->dev);
349 if ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV;
351 MOD_INC_USE_COUNT;
353 return 0;
356 static void pcd_release(struct cdrom_device_info *cdi)
358 { MOD_DEC_USE_COUNT;
361 #ifdef MODULE
363 /* Glue for modules ... */
365 int init_module(void)
367 { int err;
369 #ifdef PARIDE_JUMBO
370 { extern paride_init();
371 paride_init();
373 #endif
375 err = pcd_init();
377 return err;
380 void cleanup_module(void)
382 { int unit;
384 for (unit=0;unit<PCD_UNITS;unit++)
385 if (PCD.present) {
386 pi_release(PI);
387 unregister_cdrom(&PCD.info);
390 unregister_blkdev(MAJOR_NR,name);
393 #endif
395 #define WR(c,r,v) pi_write_regr(PI,c,r,v)
396 #define RR(c,r) (pi_read_regr(PI,c,r))
398 static int pcd_wait( int unit, int go, int stop, char * fun, char * msg )
400 { int j, r, e, s, p;
402 j = 0;
403 while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PCD_SPIN))
404 udelay(PCD_DELAY);
406 if ((r&(IDE_ERR&stop))||(j>=PCD_SPIN)) {
407 s = RR(0,7);
408 e = RR(0,1);
409 p = RR(0,2);
410 if (j >= PCD_SPIN) e |= 0x100;
411 if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
412 " loop=%d phase=%d\n",
413 PCD.name,fun,msg,r,s,e,j,p);
414 return (s<<8)+r;
416 return 0;
419 static int pcd_command( int unit, char * cmd, int dlen, char * fun )
421 { pi_connect(PI);
423 WR(0,6,0xa0 + 0x10*PCD.drive);
425 if (pcd_wait(unit,IDE_BUSY|IDE_DRQ,0,fun,"before command")) {
426 pi_disconnect(PI);
427 return -1;
430 WR(0,4,dlen % 256);
431 WR(0,5,dlen / 256);
432 WR(0,7,0xa0); /* ATAPI packet command */
434 if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) {
435 pi_disconnect(PI);
436 return -1;
439 if (RR(0,2) != 1) {
440 printk("%s: %s: command phase error\n",PCD.name,fun);
441 pi_disconnect(PI);
442 return -1;
445 pi_write_block(PI,cmd,12);
447 return 0;
450 static int pcd_completion( int unit, char * buf, char * fun )
452 { int r, d, p, n, k, j;
454 r = -1; k = 0; j = 0;
456 if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
457 fun,"completion")) {
458 r = 0;
459 while (RR(0,7)&IDE_DRQ) {
460 d = (RR(0,4)+256*RR(0,5));
461 n = ((d+3)&0xfffc);
462 p = RR(0,2)&3;
464 if ((p == 2) && (n > 0) && (j == 0)) {
465 pi_read_block(PI,buf,n);
466 if (verbose > 1)
467 printk("%s: %s: Read %d bytes\n",PCD.name,fun,n);
468 r = 0; j++;
469 } else {
470 if (verbose > 1)
471 printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
472 PCD.name,fun,p,d,k);
473 if ((verbose < 2) && !pcd_warned) {
474 pcd_warned = 1;
475 printk("%s: WARNING: ATAPI phase errors\n",PCD.name);
477 mdelay(1);
479 if (k++ > PCD_TMO) {
480 printk("%s: Stuck DRQ\n",PCD.name);
481 break;
483 if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
484 fun,"completion")) {
485 r = -1;
486 break;
491 pi_disconnect(PI);
493 return r;
496 static void pcd_req_sense( int unit, char *fun )
498 { char rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
499 char buf[16];
500 int r, c;
502 r = pcd_command(unit,rs_cmd,16,"Request sense");
503 mdelay(1);
504 if (!r) pcd_completion(unit,buf,"Request sense");
506 PCD.last_sense = -1; c = 2;
507 if (!r) {
508 if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
509 PCD.name,fun,buf[2]&0xf,buf[12],buf[13]);
510 c = buf[2]&0xf;
511 PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16);
513 if ((c == 2) || (c == 6)) PCD.changed = 1;
516 static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
518 { int r;
520 r = pcd_command(unit,cmd,dlen,fun);
521 mdelay(1);
522 if (!r) r = pcd_completion(unit,buf,fun);
523 if (r) pcd_req_sense(unit,fun);
525 return r;
528 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
530 static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
532 { int r;
533 int unit = DEVICE_NR(cdi->dev);
535 r = PCD.changed;
536 PCD.changed = 0;
538 return r;
541 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
543 { char un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 };
544 int unit = DEVICE_NR(cdi->dev);
546 return pcd_atapi(unit,un_cmd,0,pcd_scratch,
547 lock?"lock door":"unlock door");
550 static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
552 { char ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 };
553 int unit = DEVICE_NR(cdi->dev);
555 return pcd_atapi(unit,ej_cmd,0,pcd_scratch,
556 position?"eject":"close tray");
559 static void pcd_sleep( int cs )
561 { current->state = TASK_INTERRUPTIBLE;
562 schedule_timeout(cs);
565 static int pcd_reset( int unit )
567 { int i, k, flg;
568 int expect[5] = {1,1,1,0x14,0xeb};
570 pi_connect(PI);
571 WR(0,6,0xa0 + 0x10*PCD.drive);
572 WR(0,7,8);
574 pcd_sleep(2); /* delay a bit */
576 k = 0;
577 while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY))
578 pcd_sleep(HZ/10);
580 flg = 1;
581 for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
583 if (verbose) {
584 printk("%s: Reset (%d) signature = ",PCD.name,k);
585 for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
586 if (!flg) printk(" (incorrect)");
587 printk("\n");
590 pi_disconnect(PI);
591 return flg-1;
594 static int pcd_drive_reset(struct cdrom_device_info *cdi)
596 { return pcd_reset(DEVICE_NR(cdi->dev));
599 static int pcd_ready_wait( int unit, int tmo )
601 { char tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
602 int k, p;
604 k = 0;
605 while (k < tmo) {
606 PCD.last_sense = 0;
607 pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
608 p = PCD.last_sense;
609 if (!p) return 0;
610 if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
611 k++;
612 pcd_sleep(100);
614 return 0x000020; /* timeout */
617 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
619 { char rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
620 int unit = DEVICE_NR(cdi->dev);
622 if (pcd_ready_wait(unit,PCD_READY_TMO))
623 return CDS_DRIVE_NOT_READY;
624 if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")))
625 return CDS_NO_DISC;
626 return CDS_DISC_OK;
629 static int pcd_identify( int unit, char * id )
631 { int k, s;
632 char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
634 pcd_bufblk = -1;
636 s = pcd_atapi(unit,id_cmd,36,pcd_buffer,"identify");
638 if (s) return -1;
639 if ((pcd_buffer[0] & 0x1f) != 5) {
640 if (verbose) printk("%s: %s is not a CD-ROM\n",
641 PCD.name,PCD.drive?"Slave":"Master");
642 return -1;
644 for (k=0;k<16;k++) id[k] = pcd_buffer[16+k]; id[16] = 0;
645 k = 16; while ((k >= 0) && (id[k] <= 0x20)) { id[k] = 0; k--; }
647 printk("%s: %s: %s\n",PCD.name,PCD.drive?"Slave":"Master",id);
649 return 0;
652 static int pcd_probe( int unit, int ms, char * id )
654 /* returns 0, with id set if drive is detected
655 -1, if drive detection failed
658 { if (ms == -1) {
659 for (PCD.drive=0;PCD.drive<=1;PCD.drive++)
660 if (!pcd_reset(unit) && !pcd_identify(unit,id))
661 return 0;
662 } else {
663 PCD.drive = ms;
664 if (!pcd_reset(unit) && !pcd_identify(unit,id))
665 return 0;
667 return -1;
670 static int pcd_detect( void )
672 { char id[18];
673 int k, unit;
675 printk("%s: %s version %s, major %d, nice %d\n",
676 name,name,PCD_VERSION,major,nice);
678 k = 0;
679 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
680 unit = 0;
681 if (pi_init(PI,1,-1,-1,-1,-1,-1,pcd_buffer,
682 PI_PCD,verbose,PCD.name)) {
683 if (!pcd_probe(unit,-1,id)) {
684 PCD.present = 1;
685 k++;
686 } else pi_release(PI);
689 } else for (unit=0;unit<PCD_UNITS;unit++) if (DU[D_PRT])
690 if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
691 DU[D_PRO],DU[D_DLY],pcd_buffer,PI_PCD,verbose,
692 PCD.name)) {
693 if (!pcd_probe(unit,DU[D_SLV],id)) {
694 PCD.present = 1;
695 k++;
696 } else pi_release(PI);
699 if (k) return 0;
701 printk("%s: No CD-ROM drive found\n",name);
702 return -1;
705 /* I/O request processing */
707 static void do_pcd_request (void)
709 { int unit;
711 if (pcd_busy) return;
712 while (1) {
713 if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
714 INIT_REQUEST;
715 if (CURRENT->cmd == READ) {
716 unit = MINOR(CURRENT->rq_dev);
717 if (unit != pcd_unit) {
718 pcd_bufblk = -1;
719 pcd_unit = unit;
721 pcd_sector = CURRENT->sector;
722 pcd_count = CURRENT->nr_sectors;
723 pcd_buf = CURRENT->buffer;
724 pcd_busy = 1;
725 ps_set_intr(do_pcd_read,0,0,nice);
726 return;
728 else end_request(0);
732 static int pcd_ready( void )
734 { int unit = pcd_unit;
736 return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ;
739 static void pcd_transfer( void )
741 { int k, o;
743 while (pcd_count && (pcd_sector/4 == pcd_bufblk)) {
744 o = (pcd_sector % 4) * 512;
745 for(k=0;k<512;k++) pcd_buf[k] = pcd_buffer[o+k];
746 pcd_count--;
747 pcd_buf += 512;
748 pcd_sector++;
752 static void pcd_start( void )
754 { int unit = pcd_unit;
755 int b, i;
756 char rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
757 long saved_flags;
759 pcd_bufblk = pcd_sector / 4;
760 b = pcd_bufblk;
761 for(i=0;i<4;i++) {
762 rd_cmd[5-i] = b & 0xff;
763 b = b >> 8;
766 if (pcd_command(unit,rd_cmd,2048,"read block")) {
767 pcd_bufblk = -1;
768 spin_lock_irqsave(&io_request_lock,saved_flags);
769 pcd_busy = 0;
770 end_request(0);
771 do_pcd_request();
772 spin_unlock_irqrestore(&io_request_lock,saved_flags);
773 return;
776 mdelay(1);
778 ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice);
782 static void do_pcd_read( void )
785 { int unit = pcd_unit;
786 long saved_flags;
788 pcd_busy = 1;
789 pcd_retries = 0;
790 pcd_transfer();
791 if (!pcd_count) {
792 spin_lock_irqsave(&io_request_lock,saved_flags);
793 end_request(1);
794 pcd_busy = 0;
795 do_pcd_request();
796 spin_unlock_irqrestore(&io_request_lock,saved_flags);
797 return;
800 pi_do_claimed(PI,pcd_start);
803 static void do_pcd_read_drq( void )
805 { int unit = pcd_unit;
806 long saved_flags;
808 if (pcd_completion(unit,pcd_buffer,"read block")) {
809 if (pcd_retries < PCD_RETRIES) {
810 mdelay(1);
811 pcd_retries++;
812 pi_do_claimed(PI,pcd_start);
813 return;
815 spin_lock_irqsave(&io_request_lock,saved_flags);
816 pcd_busy = 0;
817 pcd_bufblk = -1;
818 end_request(0);
819 do_pcd_request();
820 spin_unlock_irqrestore(&io_request_lock,saved_flags);
821 return;
824 do_pcd_read();
825 spin_lock_irqsave(&io_request_lock,saved_flags);
826 do_pcd_request();
827 spin_unlock_irqrestore(&io_request_lock,saved_flags);
830 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
832 static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
833 unsigned int cmd, void *arg)
835 { int unit = DEVICE_NR(cdi->dev);
837 switch (cmd) {
839 case CDROMPAUSE:
841 { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
843 return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO;
846 case CDROMRESUME:
848 { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
850 return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO;
853 case CDROMPLAYMSF:
855 { char cmd[12]={GPCMD_PLAY_AUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
856 struct cdrom_msf* msf = (struct cdrom_msf*)arg;
858 cmd[3] = msf->cdmsf_min0;
859 cmd[4] = msf->cdmsf_sec0;
860 cmd[5] = msf->cdmsf_frame0;
861 cmd[6] = msf->cdmsf_min1;
862 cmd[7] = msf->cdmsf_sec1;
863 cmd[8] = msf->cdmsf_frame1;
865 return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO;
868 case CDROMPLAYBLK:
870 { char cmd[12]={GPCMD_PLAY_AUDIO_10,0,0,0,0,0,0,0,0,0,0,0};
871 struct cdrom_blk* blk = (struct cdrom_blk*)arg;
873 cmd[2] = blk->from >> 24;
874 cmd[3] = blk->from >> 16;
875 cmd[4] = blk->from >> 8;
876 cmd[5] = blk->from;
877 cmd[7] = blk->len >> 8;
878 cmd[8] = blk->len;
880 return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO;
883 case CDROMPLAYTRKIND:
885 { char cmd[12]={GPCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
886 struct cdrom_ti* ti = (struct cdrom_ti*)arg;
888 cmd[4] = ti->cdti_trk0;
889 cmd[5] = ti->cdti_ind0;
890 cmd[7] = ti->cdti_trk1;
891 cmd[8] = ti->cdti_ind1;
893 return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO;
896 case CDROMREADTOCHDR:
898 { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
899 struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
900 char buffer[32];
901 int r;
903 r = pcd_atapi(unit,cmd,12,buffer,"read toc header");
905 tochdr->cdth_trk0 = buffer[2];
906 tochdr->cdth_trk1 = buffer[3];
908 return r * EIO;
911 case CDROMREADTOCENTRY:
913 { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
915 struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
916 unsigned char buffer[32];
917 int r;
919 cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
920 cmd[6] = tocentry->cdte_track;
922 r = pcd_atapi(unit,cmd,12,buffer,"read toc entry");
924 tocentry->cdte_ctrl = buffer[5] & 0xf;
925 tocentry->cdte_adr = buffer[5] >> 4;
926 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0;
927 if (tocentry->cdte_format == CDROM_MSF) {
928 tocentry->cdte_addr.msf.minute = buffer[9];
929 tocentry->cdte_addr.msf.second = buffer[10];
930 tocentry->cdte_addr.msf.frame = buffer[11];
931 } else
932 tocentry->cdte_addr.lba =
933 (((((buffer[8] << 8) + buffer[9]) << 8)
934 + buffer[10]) << 8) + buffer[11];
936 return r * EIO;
939 case CDROMSTOP:
941 { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,0,0,0,0,0,0,0,0};
943 return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO;
946 case CDROMSTART:
948 { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,1,0,0,0,0,0,0,0};
950 return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO;
953 case CDROMVOLCTRL:
955 { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
956 char buffer[32];
957 char mask[32];
958 struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
960 cmd[2] = 0xe;
961 cmd[4] = 28;
963 if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol"))
964 return -EIO;
966 cmd[2] = 0x4e;
968 if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask"))
969 return -EIO;
971 buffer[0] = 0;
973 buffer[21] = volctrl->channel0 & mask[21];
974 buffer[23] = volctrl->channel1 & mask[23];
975 buffer[25] = volctrl->channel2 & mask[25];
976 buffer[27] = volctrl->channel3 & mask[27];
978 cmd[0] = 0x55;
979 cmd[1] = 0x10;
981 return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO;
984 case CDROMVOLREAD:
986 { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
987 char buffer[32];
988 struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
989 int r;
991 cmd[2] = 0xe;
992 cmd[4] = 28;
994 r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read");
996 volctrl->channel0 = buffer[21];
997 volctrl->channel1 = buffer[23];
998 volctrl->channel2 = buffer[25];
999 volctrl->channel3 = buffer[27];
1001 return r * EIO;
1005 case CDROMSUBCHNL:
1007 { char cmd[12]={GPCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
1008 struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
1009 char buffer[32];
1011 if (pcd_atapi(unit,cmd,16,buffer,"read subchannel"))
1012 return -EIO;
1014 subchnl->cdsc_audiostatus = buffer[1];
1015 subchnl->cdsc_format = CDROM_MSF;
1016 subchnl->cdsc_ctrl = buffer[5] & 0xf;
1017 subchnl->cdsc_trk = buffer[6];
1018 subchnl->cdsc_ind = buffer[7];
1020 subchnl->cdsc_reladdr.msf.minute = buffer[13];
1021 subchnl->cdsc_reladdr.msf.second = buffer[14];
1022 subchnl->cdsc_reladdr.msf.frame = buffer[15];
1023 subchnl->cdsc_absaddr.msf.minute = buffer[9];
1024 subchnl->cdsc_absaddr.msf.second = buffer[10];
1025 subchnl->cdsc_absaddr.msf.frame = buffer[11];
1027 return 0;
1030 default:
1032 return -ENOSYS;
1036 static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
1038 { char cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
1039 char buffer[32];
1040 int k;
1041 int unit = DEVICE_NR(cdi->dev);
1043 if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO;
1045 for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9];
1046 mcn->medium_catalog_number[13] = 0;
1048 return 0;
1051 /* end of pcd.c */