Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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