block: autoconvert trivial BKL users to private mutex
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / block / paride / pcd.c
blob62cec6afd7adf560f6792c68949f71fcc8e6f9ea
1 /*
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:
18 drive2
19 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
21 Where,
23 <prt> is the base of the parallel port address for
24 the corresponding drive. (required)
26 <pro> is the protocol number for the adapter that
27 supports this drive. These numbers are
28 logged by 'paride' when the protocol modules
29 are initialised. (0 if not given)
31 <uni> for those adapters that support chained
32 devices, this is the unit selector for the
33 chain of devices on the given port. It should
34 be zero for devices that don't support chaining.
35 (0 if not given)
37 <mod> this can be -1 to choose the best mode, or one
38 of the mode numbers supported by the adapter.
39 (-1 if not given)
41 <slv> ATAPI CD-ROMs can be jumpered to master or slave.
42 Set this to 0 to choose the master drive, 1 to
43 choose the slave, -1 (the default) to choose the
44 first drive found.
46 <dly> some parallel ports require the driver to
47 go more slowly. -1 sets a default value that
48 should work with the chosen protocol. Otherwise,
49 set this to a small integer, the larger it is
50 the slower the port i/o. In some cases, setting
51 this to zero will speed up the device. (default -1)
53 major You may use this parameter to overide the
54 default major number (46) that this driver
55 will use. Be sure to change the device
56 name as well.
58 name This parameter is a character string that
59 contains the name the kernel will use for this
60 device (in /proc output, for instance).
61 (default "pcd")
63 verbose This parameter controls the amount of logging
64 that the driver will do. Set it to 0 for
65 normal operation, 1 to see autoprobe progress
66 messages, or 2 to see additional debugging
67 output. (default 0)
69 nice This parameter controls the driver's use of
70 idle CPU time, at the expense of some speed.
72 If this driver is built into the kernel, you can use kernel
73 the following command line parameters, with the same values
74 as the corresponding module parameters listed above:
76 pcd.drive0
77 pcd.drive1
78 pcd.drive2
79 pcd.drive3
80 pcd.nice
82 In addition, you can use the parameter pcd.disable to disable
83 the driver entirely.
87 /* Changes:
89 1.01 GRG 1998.01.24 Added test unit ready support
90 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait,
91 and loosen interpretation of ATAPI
92 standard for clearing error status.
93 Use spinlocks. Eliminate sti().
94 1.03 GRG 1998.06.16 Eliminated an Ugh
95 1.04 GRG 1998.08.15 Added extra debugging, improvements to
96 pcd_completion, use HZ in loop timing
97 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard
98 1.06 GRG 1998.08.19 Added audio ioctl support
99 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support
103 #define PCD_VERSION "1.07"
104 #define PCD_MAJOR 46
105 #define PCD_NAME "pcd"
106 #define PCD_UNITS 4
108 /* Here are things one can override from the insmod command.
109 Most are autoprobed by paride unless set here. Verbose is off
110 by default.
114 static int verbose = 0;
115 static int major = PCD_MAJOR;
116 static char *name = PCD_NAME;
117 static int nice = 0;
118 static int disable = 0;
120 static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
121 static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
122 static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
123 static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
125 static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
126 static int pcd_drive_count;
128 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);
156 #include "paride.h"
157 #include "pseudo.h"
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)
167 #define IDE_ERR 0x01
168 #define IDE_DRQ 0x08
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);
191 struct pcd_unit {
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
209 pd_unit.
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;
229 int ret;
231 mutex_lock(&pcd_mutex);
232 ret = cdrom_open(&cd->info, bdev, mode);
233 mutex_unlock(&pcd_mutex);
235 return ret;
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);
244 return 0;
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;
251 int ret;
253 mutex_lock(&pcd_mutex);
254 ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
255 mutex_unlock(&pcd_mutex);
257 return ret;
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 = {
275 .open = pcd_open,
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 |
288 CDC_CD_RW,
291 static void pcd_init_units(void)
293 struct pcd_unit *cd;
294 int unit;
296 pcd_drive_count = 0;
297 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
298 struct gendisk *disk = alloc_disk(1);
299 if (!disk)
300 continue;
301 cd->disk = disk;
302 cd->pi = &cd->pia;
303 cd->present = 0;
304 cd->last_sense = 0;
305 cd->changed = 1;
306 cd->drive = (*drives[unit])[D_SLV];
307 if ((*drives[unit])[D_PRT])
308 pcd_drive_count++;
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;
314 cd->info.speed = 0;
315 cd->info.capacity = 1;
316 cd->info.mask = 0;
317 disk->major = major;
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;
327 if (!cd->present)
328 return -ENODEV;
329 return 0;
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)
353 int j, r, e, s, p;
355 j = 0;
356 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
357 && (j++ < PCD_SPIN))
358 udelay(PCD_DELAY);
360 if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
361 s = read_reg(cd, 7);
362 e = read_reg(cd, 1);
363 p = read_reg(cd, 2);
364 if (j > PCD_SPIN)
365 e |= 0x100;
366 if (fun)
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);
370 return (s << 8) + r;
372 return 0;
375 static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
377 pi_connect(cd->pi);
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);
383 return -1;
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);
392 return -1;
395 if (read_reg(cd, 2) != 1) {
396 printk("%s: %s: command phase error\n", cd->name, fun);
397 pi_disconnect(cd->pi);
398 return -1;
401 pi_write_block(cd->pi, cmd, 12);
403 return 0;
406 static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
408 int r, d, p, n, k, j;
410 r = -1;
411 k = 0;
412 j = 0;
414 if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
415 fun, "completion")) {
416 r = 0;
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);
424 if (verbose > 1)
425 printk("%s: %s: Read %d bytes\n",
426 cd->name, fun, n);
427 r = 0;
428 j++;
429 } else {
430 if (verbose > 1)
431 printk
432 ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
433 cd->name, fun, p, d, k);
434 if (verbose < 2)
435 printk_once(
436 "%s: WARNING: ATAPI phase errors\n",
437 cd->name);
438 mdelay(1);
440 if (k++ > PCD_TMO) {
441 printk("%s: Stuck DRQ\n", cd->name);
442 break;
444 if (pcd_wait
445 (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
446 "completion")) {
447 r = -1;
448 break;
453 pi_disconnect(cd->pi);
455 return r;
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 };
461 char buf[16];
462 int r, c;
464 r = pcd_command(cd, rs_cmd, 16, "Request sense");
465 mdelay(1);
466 if (!r)
467 pcd_completion(cd, buf, "Request sense");
469 cd->last_sense = -1;
470 c = 2;
471 if (!r) {
472 if (fun)
473 printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
474 cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
475 c = buf[2] & 0xf;
476 cd->last_sense =
477 c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
479 if ((c == 2) || (c == 6))
480 cd->changed = 1;
483 static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
485 int r;
487 r = pcd_command(cd, cmd, dlen, fun);
488 mdelay(1);
489 if (!r)
490 r = pcd_completion(cd, buf, fun);
491 if (r)
492 pcd_req_sense(cd, fun);
494 return r;
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,
500 "generic packet");
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;
509 if (res)
510 cd->changed = 0;
511 return res;
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)
537 int i, k, flg;
538 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
540 pi_connect(cd->pi);
541 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
542 write_reg(cd, 7, 8);
544 pcd_sleep(20 * HZ / 1000); /* delay a bit */
546 k = 0;
547 while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
548 pcd_sleep(HZ / 10);
550 flg = 1;
551 for (i = 0; i < 5; i++)
552 flg &= (read_reg(cd, i + 1) == expect[i]);
554 if (verbose) {
555 printk("%s: Reset (%d) signature = ", cd->name, k);
556 for (i = 0; i < 5; i++)
557 printk("%3x", read_reg(cd, i + 1));
558 if (!flg)
559 printk(" (incorrect)");
560 printk("\n");
563 pi_disconnect(cd->pi);
564 return flg - 1;
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 };
575 int k, p;
577 k = 0;
578 while (k < tmo) {
579 cd->last_sense = 0;
580 pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
581 p = cd->last_sense;
582 if (!p)
583 return 0;
584 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
585 return p;
586 k++;
587 pcd_sleep(HZ);
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")))
600 return CDS_NO_DISC;
601 return CDS_DISC_OK;
604 static int pcd_identify(struct pcd_unit *cd, char *id)
606 int k, s;
607 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
609 pcd_bufblk = -1;
611 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
613 if (s)
614 return -1;
615 if ((pcd_buffer[0] & 0x1f) != 5) {
616 if (verbose)
617 printk("%s: %s is not a CD-ROM\n",
618 cd->name, cd->drive ? "Slave" : "Master");
619 return -1;
621 memcpy(id, pcd_buffer + 16, 16);
622 id[16] = 0;
623 k = 16;
624 while ((k >= 0) && (id[k] <= 0x20)) {
625 id[k] = 0;
626 k--;
629 printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
631 return 0;
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)
640 if (ms == -1) {
641 for (cd->drive = 0; cd->drive <= 1; cd->drive++)
642 if (!pcd_reset(cd) && !pcd_identify(cd, id))
643 return 0;
644 } else {
645 cd->drive = ms;
646 if (!pcd_reset(cd) && !pcd_identify(cd, id))
647 return 0;
649 return -1;
652 static void pcd_probe_capabilities(void)
654 int unit, r;
655 char buffer[32];
656 char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
657 struct pcd_unit *cd;
659 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
660 if (!cd->present)
661 continue;
662 r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
663 if (r)
664 continue;
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)
683 char id[18];
684 int k, unit;
685 struct pcd_unit *cd;
687 printk("%s: %s version %s, major %d, nice %d\n",
688 name, name, PCD_VERSION, major, nice);
690 k = 0;
691 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
692 cd = pcd;
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) {
696 cd->present = 1;
697 k++;
698 } else
699 pi_release(cd->pi);
701 } else {
702 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
703 int *conf = *drives[unit];
704 if (!conf[D_PRT])
705 continue;
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))
709 continue;
710 if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
711 cd->present = 1;
712 k++;
713 } else
714 pi_release(cd->pi);
717 if (k)
718 return 0;
720 printk("%s: No CD-ROM drive found\n", name);
721 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
722 put_disk(cd->disk);
723 return -1;
726 /* I/O request processing */
727 static struct request_queue *pcd_queue;
729 static void do_pcd_request(struct request_queue * q)
731 if (pcd_busy)
732 return;
733 while (1) {
734 if (!pcd_req) {
735 pcd_req = blk_fetch_request(q);
736 if (!pcd_req)
737 return;
740 if (rq_data_dir(pcd_req) == READ) {
741 struct pcd_unit *cd = pcd_req->rq_disk->private_data;
742 if (cd != pcd_current)
743 pcd_bufblk = -1;
744 pcd_current = cd;
745 pcd_sector = blk_rq_pos(pcd_req);
746 pcd_count = blk_rq_cur_sectors(pcd_req);
747 pcd_buf = pcd_req->buffer;
748 pcd_busy = 1;
749 ps_set_intr(do_pcd_read, NULL, 0, nice);
750 return;
751 } else {
752 __blk_end_request_all(pcd_req, -EIO);
753 pcd_req = NULL;
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))
764 pcd_req = NULL;
765 pcd_busy = 0;
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);
781 pcd_count--;
782 pcd_buf += 512;
783 pcd_sector++;
787 static void pcd_start(void)
789 int b, i;
790 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
792 pcd_bufblk = pcd_sector / 4;
793 b = pcd_bufblk;
794 for (i = 0; i < 4; i++) {
795 rd_cmd[5 - i] = b & 0xff;
796 b = b >> 8;
799 if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
800 pcd_bufblk = -1;
801 next_request(-EIO);
802 return;
805 mdelay(1);
807 ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
810 static void do_pcd_read(void)
812 pcd_busy = 1;
813 pcd_retries = 0;
814 pcd_transfer();
815 if (!pcd_count) {
816 next_request(0);
817 return;
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) {
829 mdelay(1);
830 pcd_retries++;
831 pi_do_claimed(pcd_current->pi, pcd_start);
832 return;
834 pcd_bufblk = -1;
835 next_request(-EIO);
836 return;
839 do_pcd_read();
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;
851 switch (cmd) {
853 case CDROMREADTOCHDR:
856 char cmd[12] =
857 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
858 0, 0, 0 };
859 struct cdrom_tochdr *tochdr =
860 (struct cdrom_tochdr *) arg;
861 char buffer[32];
862 int r;
864 r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
866 tochdr->cdth_trk0 = buffer[2];
867 tochdr->cdth_trk1 = buffer[3];
869 return r ? -EIO : 0;
872 case CDROMREADTOCENTRY:
875 char cmd[12] =
876 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
877 0, 0, 0 };
879 struct cdrom_tocentry *tocentry =
880 (struct cdrom_tocentry *) arg;
881 unsigned char buffer[32];
882 int r;
884 cmd[1] =
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];
898 } else
899 tocentry->cdte_addr.lba =
900 (((((buffer[8] << 8) + buffer[9]) << 8)
901 + buffer[10]) << 8) + buffer[11];
903 return r ? -EIO : 0;
906 default:
908 return -ENOSYS;
912 static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
914 char cmd[12] =
915 { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
916 char buffer[32];
918 if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
919 return -EIO;
921 memcpy(mcn->medium_catalog_number, buffer + 9, 13);
922 mcn->medium_catalog_number[13] = 0;
924 return 0;
927 static int __init pcd_init(void)
929 struct pcd_unit *cd;
930 int unit;
932 if (disable)
933 return -EINVAL;
935 pcd_init_units();
937 if (pcd_detect())
938 return -ENODEV;
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++)
945 put_disk(cd->disk);
946 return -EBUSY;
949 pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
950 if (!pcd_queue) {
951 unregister_blkdev(major, name);
952 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
953 put_disk(cd->disk);
954 return -ENOMEM;
957 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
958 if (cd->present) {
959 register_cdrom(&cd->info);
960 cd->disk->private_data = cd;
961 cd->disk->queue = pcd_queue;
962 add_disk(cd->disk);
966 return 0;
969 static void __exit pcd_exit(void)
971 struct pcd_unit *cd;
972 int unit;
974 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
975 if (cd->present) {
976 del_gendisk(cd->disk);
977 pi_release(cd->pi);
978 unregister_cdrom(&cd->info);
980 put_disk(cd->disk);
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)