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