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