2 pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU General Public License.
5 This is a high-level driver for parallel port ATAPI CD-ROM
6 drives based on chips supported by the paride module.
8 By default, the driver will autoprobe for a single parallel
9 port ATAPI CD-ROM drive, but if their individual parameters are
10 specified, the driver can handle up to 4 drives.
12 The behaviour of the pcd driver can be altered by setting
13 some parameters from the insmod command line. The following
14 parameters are adjustable:
16 drive0 These four arguments can be arrays of
17 drive1 1-6 integers as follows:
19 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
23 <prt> is the base of the parallel port address for
24 the corresponding drive. (required)
26 <pro> is the protocol number for the adapter that
27 supports this drive. These numbers are
28 logged by 'paride' when the protocol modules
29 are initialised. (0 if not given)
31 <uni> for those adapters that support chained
32 devices, this is the unit selector for the
33 chain of devices on the given port. It should
34 be zero for devices that don't support chaining.
37 <mod> this can be -1 to choose the best mode, or one
38 of the mode numbers supported by the adapter.
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
46 <dly> some parallel ports require the driver to
47 go more slowly. -1 sets a default value that
48 should work with the chosen protocol. Otherwise,
49 set this to a small integer, the larger it is
50 the slower the port i/o. In some cases, setting
51 this to zero will speed up the device. (default -1)
53 major You may use this parameter to overide the
54 default major number (46) that this driver
55 will use. Be sure to change the device
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).
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
69 nice This parameter controls the driver's use of
70 idle CPU time, at the expense of some speed.
72 If this driver is built into the kernel, you can use kernel
73 the following command line parameters, with the same values
74 as the corresponding module parameters listed above:
82 In addition, you can use the parameter pcd.disable to disable
89 1.01 GRG 1998.01.24 Added test unit ready support
90 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait,
91 and loosen interpretation of ATAPI
92 standard for clearing error status.
93 Use spinlocks. Eliminate sti().
94 1.03 GRG 1998.06.16 Eliminated an Ugh
95 1.04 GRG 1998.08.15 Added extra debugging, improvements to
96 pcd_completion, use HZ in loop timing
97 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard
98 1.06 GRG 1998.08.19 Added audio ioctl support
99 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support
103 #define PCD_VERSION "1.07"
105 #define PCD_NAME "pcd"
108 /* Here are things one can override from the insmod command.
109 Most are autoprobed by paride unless set here. Verbose is off
114 static int verbose = 0;
115 static int major = PCD_MAJOR;
116 static char *name = PCD_NAME;
118 static int disable = 0;
120 static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
121 static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
122 static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
123 static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
125 static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
126 static int pcd_drive_count;
128 enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
130 /* end of parameters */
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 <linux/mutex.h>
142 #include <asm/uaccess.h>
144 static DEFINE_MUTEX(pcd_mutex);
145 static DEFINE_SPINLOCK(pcd_lock);
147 module_param(verbose, bool, 0644);
148 module_param(major, int, 0);
149 module_param(name, charp, 0);
150 module_param(nice, int, 0);
151 module_param_array(drive0, int, NULL, 0);
152 module_param_array(drive1, int, NULL, 0);
153 module_param_array(drive2, int, NULL, 0);
154 module_param_array(drive3, int, NULL, 0);
159 #define PCD_RETRIES 5
160 #define PCD_TMO 800 /* timeout in jiffies */
161 #define PCD_DELAY 50 /* spin delay in uS */
162 #define PCD_READY_TMO 20 /* in seconds */
163 #define PCD_RESET_TMO 100 /* in tenths of a second */
165 #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
169 #define IDE_READY 0x40
170 #define IDE_BUSY 0x80
172 static int pcd_open(struct cdrom_device_info *cdi, int purpose);
173 static void pcd_release(struct cdrom_device_info *cdi);
174 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
175 static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
176 static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
177 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
178 static int pcd_drive_reset(struct cdrom_device_info *cdi);
179 static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
180 static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
181 unsigned int cmd, void *arg);
182 static int pcd_packet(struct cdrom_device_info *cdi,
183 struct packet_command *cgc);
185 static int pcd_detect(void);
186 static void pcd_probe_capabilities(void);
187 static void do_pcd_read_drq(void);
188 static void do_pcd_request(struct request_queue * q);
189 static void do_pcd_read(void);
192 struct pi_adapter pia; /* interface to paride layer */
193 struct pi_adapter *pi;
194 int drive; /* master/slave */
195 int last_sense; /* result of last request sense */
196 int changed; /* media change seen */
197 int present; /* does this unit exist ? */
198 char *name; /* pcd0, pcd1, etc */
199 struct cdrom_device_info info; /* uniform cdrom interface */
200 struct gendisk *disk;
203 static struct pcd_unit pcd[PCD_UNITS];
205 static char pcd_scratch[64];
206 static char pcd_buffer[2048]; /* raw block buffer */
207 static int pcd_bufblk = -1; /* block in buffer, in CD units,
208 -1 for nothing there. See also
212 /* the variables below are used mainly in the I/O request engine, which
213 processes only one request at a time.
216 static struct pcd_unit *pcd_current; /* current request's drive */
217 static struct request *pcd_req;
218 static int pcd_retries; /* retries on current request */
219 static int pcd_busy; /* request being processed ? */
220 static int pcd_sector; /* address of next requested sector */
221 static int pcd_count; /* number of blocks still to do */
222 static char *pcd_buf; /* buffer for request in progress */
224 /* kernel glue structures */
226 static int pcd_block_open(struct block_device *bdev, fmode_t mode)
228 struct pcd_unit *cd = bdev->bd_disk->private_data;
231 mutex_lock(&pcd_mutex);
232 ret = cdrom_open(&cd->info, bdev, mode);
233 mutex_unlock(&pcd_mutex);
238 static int pcd_block_release(struct gendisk *disk, fmode_t mode)
240 struct pcd_unit *cd = disk->private_data;
241 mutex_lock(&pcd_mutex);
242 cdrom_release(&cd->info, mode);
243 mutex_unlock(&pcd_mutex);
247 static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
248 unsigned cmd, unsigned long arg)
250 struct pcd_unit *cd = bdev->bd_disk->private_data;
253 mutex_lock(&pcd_mutex);
254 ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
255 mutex_unlock(&pcd_mutex);
260 static int pcd_block_media_changed(struct gendisk *disk)
262 struct pcd_unit *cd = disk->private_data;
263 return cdrom_media_changed(&cd->info);
266 static const struct block_device_operations pcd_bdops = {
267 .owner = THIS_MODULE,
268 .open = pcd_block_open,
269 .release = pcd_block_release,
270 .ioctl = pcd_block_ioctl,
271 .media_changed = pcd_block_media_changed,
274 static struct cdrom_device_ops pcd_dops = {
276 .release = pcd_release,
277 .drive_status = pcd_drive_status,
278 .media_changed = pcd_media_changed,
279 .tray_move = pcd_tray_move,
280 .lock_door = pcd_lock_door,
281 .get_mcn = pcd_get_mcn,
282 .reset = pcd_drive_reset,
283 .audio_ioctl = pcd_audio_ioctl,
284 .generic_packet = pcd_packet,
285 .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
286 CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
287 CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
291 static void pcd_init_units(void)
297 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
298 struct gendisk *disk = alloc_disk(1);
306 cd->drive = (*drives[unit])[D_SLV];
307 if ((*drives[unit])[D_PRT])
310 cd->name = &cd->info.name[0];
311 snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
312 cd->info.ops = &pcd_dops;
313 cd->info.handle = cd;
315 cd->info.capacity = 1;
318 disk->first_minor = unit;
319 strcpy(disk->disk_name, cd->name); /* umm... */
320 disk->fops = &pcd_bdops;
324 static int pcd_open(struct cdrom_device_info *cdi, int purpose)
326 struct pcd_unit *cd = cdi->handle;
332 static void pcd_release(struct cdrom_device_info *cdi)
336 static inline int status_reg(struct pcd_unit *cd)
338 return pi_read_regr(cd->pi, 1, 6);
341 static inline int read_reg(struct pcd_unit *cd, int reg)
343 return pi_read_regr(cd->pi, 0, reg);
346 static inline void write_reg(struct pcd_unit *cd, int reg, int val)
348 pi_write_regr(cd->pi, 0, reg, val);
351 static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
356 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
360 if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
367 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
368 " loop=%d phase=%d\n",
369 cd->name, fun, msg, r, s, e, j, p);
375 static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
379 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
381 if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
382 pi_disconnect(cd->pi);
386 write_reg(cd, 4, dlen % 256);
387 write_reg(cd, 5, dlen / 256);
388 write_reg(cd, 7, 0xa0); /* ATAPI packet command */
390 if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
391 pi_disconnect(cd->pi);
395 if (read_reg(cd, 2) != 1) {
396 printk("%s: %s: command phase error\n", cd->name, fun);
397 pi_disconnect(cd->pi);
401 pi_write_block(cd->pi, cmd, 12);
406 static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
408 int r, d, p, n, k, j;
414 if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
415 fun, "completion")) {
417 while (read_reg(cd, 7) & IDE_DRQ) {
418 d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
419 n = (d + 3) & 0xfffc;
420 p = read_reg(cd, 2) & 3;
422 if ((p == 2) && (n > 0) && (j == 0)) {
423 pi_read_block(cd->pi, buf, n);
425 printk("%s: %s: Read %d bytes\n",
432 ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
433 cd->name, fun, p, d, k);
436 "%s: WARNING: ATAPI phase errors\n",
441 printk("%s: Stuck DRQ\n", cd->name);
445 (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
453 pi_disconnect(cd->pi);
458 static void pcd_req_sense(struct pcd_unit *cd, char *fun)
460 char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
464 r = pcd_command(cd, rs_cmd, 16, "Request sense");
467 pcd_completion(cd, buf, "Request sense");
473 printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
474 cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
477 c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
479 if ((c == 2) || (c == 6))
483 static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
487 r = pcd_command(cd, cmd, dlen, fun);
490 r = pcd_completion(cd, buf, fun);
492 pcd_req_sense(cd, fun);
497 static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
499 return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
503 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
505 static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
507 struct pcd_unit *cd = cdi->handle;
508 int res = cd->changed;
514 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
516 char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
518 return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
519 lock ? "lock door" : "unlock door");
522 static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
524 char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
526 return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
527 position ? "eject" : "close tray");
530 static void pcd_sleep(int cs)
532 schedule_timeout_interruptible(cs);
535 static int pcd_reset(struct pcd_unit *cd)
538 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
541 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
544 pcd_sleep(20 * HZ / 1000); /* delay a bit */
547 while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
551 for (i = 0; i < 5; i++)
552 flg &= (read_reg(cd, i + 1) == expect[i]);
555 printk("%s: Reset (%d) signature = ", cd->name, k);
556 for (i = 0; i < 5; i++)
557 printk("%3x", read_reg(cd, i + 1));
559 printk(" (incorrect)");
563 pi_disconnect(cd->pi);
567 static int pcd_drive_reset(struct cdrom_device_info *cdi)
569 return pcd_reset(cdi->handle);
572 static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
574 char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
580 pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
584 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
589 return 0x000020; /* timeout */
592 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
594 char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
595 struct pcd_unit *cd = cdi->handle;
597 if (pcd_ready_wait(cd, PCD_READY_TMO))
598 return CDS_DRIVE_NOT_READY;
599 if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
604 static int pcd_identify(struct pcd_unit *cd, char *id)
607 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
611 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
615 if ((pcd_buffer[0] & 0x1f) != 5) {
617 printk("%s: %s is not a CD-ROM\n",
618 cd->name, cd->drive ? "Slave" : "Master");
621 memcpy(id, pcd_buffer + 16, 16);
624 while ((k >= 0) && (id[k] <= 0x20)) {
629 printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
635 * returns 0, with id set if drive is detected
636 * -1, if drive detection failed
638 static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
641 for (cd->drive = 0; cd->drive <= 1; cd->drive++)
642 if (!pcd_reset(cd) && !pcd_identify(cd, id))
646 if (!pcd_reset(cd) && !pcd_identify(cd, id))
652 static void pcd_probe_capabilities(void)
656 char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
659 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
662 r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
665 /* we should now have the cap page */
666 if ((buffer[11] & 1) == 0)
667 cd->info.mask |= CDC_CD_R;
668 if ((buffer[11] & 2) == 0)
669 cd->info.mask |= CDC_CD_RW;
670 if ((buffer[12] & 1) == 0)
671 cd->info.mask |= CDC_PLAY_AUDIO;
672 if ((buffer[14] & 1) == 0)
673 cd->info.mask |= CDC_LOCK;
674 if ((buffer[14] & 8) == 0)
675 cd->info.mask |= CDC_OPEN_TRAY;
676 if ((buffer[14] >> 6) == 0)
677 cd->info.mask |= CDC_CLOSE_TRAY;
681 static int pcd_detect(void)
687 printk("%s: %s version %s, major %d, nice %d\n",
688 name, name, PCD_VERSION, major, nice);
691 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
693 if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
694 PI_PCD, verbose, cd->name)) {
695 if (!pcd_probe(cd, -1, id) && cd->disk) {
702 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
703 int *conf = *drives[unit];
706 if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
707 conf[D_UNI], conf[D_PRO], conf[D_DLY],
708 pcd_buffer, PI_PCD, verbose, cd->name))
710 if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
720 printk("%s: No CD-ROM drive found\n", name);
721 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
726 /* I/O request processing */
727 static struct request_queue *pcd_queue;
729 static void do_pcd_request(struct request_queue * q)
735 pcd_req = blk_fetch_request(q);
740 if (rq_data_dir(pcd_req) == READ) {
741 struct pcd_unit *cd = pcd_req->rq_disk->private_data;
742 if (cd != pcd_current)
745 pcd_sector = blk_rq_pos(pcd_req);
746 pcd_count = blk_rq_cur_sectors(pcd_req);
747 pcd_buf = pcd_req->buffer;
749 ps_set_intr(do_pcd_read, NULL, 0, nice);
752 __blk_end_request_all(pcd_req, -EIO);
758 static inline void next_request(int err)
760 unsigned long saved_flags;
762 spin_lock_irqsave(&pcd_lock, saved_flags);
763 if (!__blk_end_request_cur(pcd_req, err))
766 do_pcd_request(pcd_queue);
767 spin_unlock_irqrestore(&pcd_lock, saved_flags);
770 static int pcd_ready(void)
772 return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
775 static void pcd_transfer(void)
778 while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
779 int o = (pcd_sector % 4) * 512;
780 memcpy(pcd_buf, pcd_buffer + o, 512);
787 static void pcd_start(void)
790 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
792 pcd_bufblk = pcd_sector / 4;
794 for (i = 0; i < 4; i++) {
795 rd_cmd[5 - i] = b & 0xff;
799 if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
807 ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
810 static void do_pcd_read(void)
820 pi_do_claimed(pcd_current->pi, pcd_start);
823 static void do_pcd_read_drq(void)
825 unsigned long saved_flags;
827 if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
828 if (pcd_retries < PCD_RETRIES) {
831 pi_do_claimed(pcd_current->pi, pcd_start);
840 spin_lock_irqsave(&pcd_lock, saved_flags);
841 do_pcd_request(pcd_queue);
842 spin_unlock_irqrestore(&pcd_lock, saved_flags);
845 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
847 static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
849 struct pcd_unit *cd = cdi->handle;
853 case CDROMREADTOCHDR:
857 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
859 struct cdrom_tochdr *tochdr =
860 (struct cdrom_tochdr *) arg;
864 r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
866 tochdr->cdth_trk0 = buffer[2];
867 tochdr->cdth_trk1 = buffer[3];
872 case CDROMREADTOCENTRY:
876 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
879 struct cdrom_tocentry *tocentry =
880 (struct cdrom_tocentry *) arg;
881 unsigned char buffer[32];
885 (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
886 cmd[6] = tocentry->cdte_track;
888 r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
890 tocentry->cdte_ctrl = buffer[5] & 0xf;
891 tocentry->cdte_adr = buffer[5] >> 4;
892 tocentry->cdte_datamode =
893 (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
894 if (tocentry->cdte_format == CDROM_MSF) {
895 tocentry->cdte_addr.msf.minute = buffer[9];
896 tocentry->cdte_addr.msf.second = buffer[10];
897 tocentry->cdte_addr.msf.frame = buffer[11];
899 tocentry->cdte_addr.lba =
900 (((((buffer[8] << 8) + buffer[9]) << 8)
901 + buffer[10]) << 8) + buffer[11];
912 static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
915 { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
918 if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
921 memcpy(mcn->medium_catalog_number, buffer + 9, 13);
922 mcn->medium_catalog_number[13] = 0;
927 static int __init pcd_init(void)
940 /* get the atapi capabilities page */
941 pcd_probe_capabilities();
943 if (register_blkdev(major, name)) {
944 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
949 pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
951 unregister_blkdev(major, name);
952 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
957 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
959 register_cdrom(&cd->info);
960 cd->disk->private_data = cd;
961 cd->disk->queue = pcd_queue;
969 static void __exit pcd_exit(void)
974 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
976 del_gendisk(cd->disk);
978 unregister_cdrom(&cd->info);
982 blk_cleanup_queue(pcd_queue);
983 unregister_blkdev(major, name);
986 MODULE_LICENSE("GPL");
987 module_init(pcd_init)
988 module_exit(pcd_exit)