]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/block/paride/pcd.c
block: autoconvert trivial BKL users to private mutex
[net-next-2.6.git] / drivers / block / paride / pcd.c
CommitLineData
1da177e4
LT
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
114static int verbose = 0;
115static int major = PCD_MAJOR;
116static char *name = PCD_NAME;
117static int nice = 0;
118static int disable = 0;
119
120static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
121static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
122static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
123static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
124
125static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
126static int pcd_drive_count;
127
128enum {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>
2a48fc0a 141#include <linux/mutex.h>
1da177e4
LT
142#include <asm/uaccess.h>
143
2a48fc0a 144static DEFINE_MUTEX(pcd_mutex);
671d40f4 145static DEFINE_SPINLOCK(pcd_lock);
1da177e4
LT
146
147module_param(verbose, bool, 0644);
148module_param(major, int, 0);
149module_param(name, charp, 0);
150module_param(nice, int, 0);
151module_param_array(drive0, int, NULL, 0);
152module_param_array(drive1, int, NULL, 0);
153module_param_array(drive2, int, NULL, 0);
154module_param_array(drive3, int, NULL, 0);
155
156#include "paride.h"
157#include "pseudo.h"
158
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 */
164
165#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
166
167#define IDE_ERR 0x01
168#define IDE_DRQ 0x08
169#define IDE_READY 0x40
170#define IDE_BUSY 0x80
171
172static int pcd_open(struct cdrom_device_info *cdi, int purpose);
173static void pcd_release(struct cdrom_device_info *cdi);
174static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
175static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
176static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
177static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
178static int pcd_drive_reset(struct cdrom_device_info *cdi);
179static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
180static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
181 unsigned int cmd, void *arg);
182static int pcd_packet(struct cdrom_device_info *cdi,
183 struct packet_command *cgc);
184
185static int pcd_detect(void);
186static void pcd_probe_capabilities(void);
187static void do_pcd_read_drq(void);
165125e1 188static void do_pcd_request(struct request_queue * q);
1da177e4
LT
189static void do_pcd_read(void);
190
191struct 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;
201};
202
203static struct pcd_unit pcd[PCD_UNITS];
204
205static char pcd_scratch[64];
206static char pcd_buffer[2048]; /* raw block buffer */
207static int pcd_bufblk = -1; /* block in buffer, in CD units,
208 -1 for nothing there. See also
209 pd_unit.
210 */
211
212/* the variables below are used mainly in the I/O request engine, which
213 processes only one request at a time.
214*/
215
216static struct pcd_unit *pcd_current; /* current request's drive */
217static struct request *pcd_req;
218static int pcd_retries; /* retries on current request */
219static int pcd_busy; /* request being processed ? */
220static int pcd_sector; /* address of next requested sector */
221static int pcd_count; /* number of blocks still to do */
222static char *pcd_buf; /* buffer for request in progress */
223
1da177e4
LT
224/* kernel glue structures */
225
c9acf903 226static int pcd_block_open(struct block_device *bdev, fmode_t mode)
1da177e4 227{
c9acf903 228 struct pcd_unit *cd = bdev->bd_disk->private_data;
6e9624b8
AB
229 int ret;
230
2a48fc0a 231 mutex_lock(&pcd_mutex);
6e9624b8 232 ret = cdrom_open(&cd->info, bdev, mode);
2a48fc0a 233 mutex_unlock(&pcd_mutex);
6e9624b8
AB
234
235 return ret;
1da177e4
LT
236}
237
c9acf903 238static int pcd_block_release(struct gendisk *disk, fmode_t mode)
1da177e4 239{
c9acf903 240 struct pcd_unit *cd = disk->private_data;
2a48fc0a 241 mutex_lock(&pcd_mutex);
c9acf903 242 cdrom_release(&cd->info, mode);
2a48fc0a 243 mutex_unlock(&pcd_mutex);
bbc1cc97 244 return 0;
1da177e4
LT
245}
246
c9acf903 247static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
1da177e4
LT
248 unsigned cmd, unsigned long arg)
249{
c9acf903 250 struct pcd_unit *cd = bdev->bd_disk->private_data;
8a6cfeb6
AB
251 int ret;
252
2a48fc0a 253 mutex_lock(&pcd_mutex);
8a6cfeb6 254 ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
2a48fc0a 255 mutex_unlock(&pcd_mutex);
8a6cfeb6
AB
256
257 return ret;
1da177e4
LT
258}
259
260static int pcd_block_media_changed(struct gendisk *disk)
261{
262 struct pcd_unit *cd = disk->private_data;
263 return cdrom_media_changed(&cd->info);
264}
265
83d5cde4 266static const struct block_device_operations pcd_bdops = {
1da177e4 267 .owner = THIS_MODULE,
c9acf903
AV
268 .open = pcd_block_open,
269 .release = pcd_block_release,
8a6cfeb6 270 .ioctl = pcd_block_ioctl,
1da177e4
LT
271 .media_changed = pcd_block_media_changed,
272};
273
274static 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,
289};
290
291static void pcd_init_units(void)
292{
293 struct pcd_unit *cd;
294 int unit;
295
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++;
309
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;
321 }
322}
323
324static int pcd_open(struct cdrom_device_info *cdi, int purpose)
325{
326 struct pcd_unit *cd = cdi->handle;
327 if (!cd->present)
328 return -ENODEV;
329 return 0;
330}
331
332static void pcd_release(struct cdrom_device_info *cdi)
333{
334}
335
336static inline int status_reg(struct pcd_unit *cd)
337{
338 return pi_read_regr(cd->pi, 1, 6);
339}
340
341static inline int read_reg(struct pcd_unit *cd, int reg)
342{
343 return pi_read_regr(cd->pi, 0, reg);
344}
345
346static inline void write_reg(struct pcd_unit *cd, int reg, int val)
347{
348 pi_write_regr(cd->pi, 0, reg, val);
349}
350
351static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
352{
353 int j, r, e, s, p;
354
355 j = 0;
356 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
357 && (j++ < PCD_SPIN))
358 udelay(PCD_DELAY);
359
c12ec0a2 360 if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
1da177e4
LT
361 s = read_reg(cd, 7);
362 e = read_reg(cd, 1);
363 p = read_reg(cd, 2);
c12ec0a2 364 if (j > PCD_SPIN)
1da177e4
LT
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;
371 }
372 return 0;
373}
374
375static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
376{
377 pi_connect(cd->pi);
378
379 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
380
381 if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
382 pi_disconnect(cd->pi);
383 return -1;
384 }
385
386 write_reg(cd, 4, dlen % 256);
387 write_reg(cd, 5, dlen / 256);
388 write_reg(cd, 7, 0xa0); /* ATAPI packet command */
389
390 if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
391 pi_disconnect(cd->pi);
392 return -1;
393 }
394
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;
399 }
400
401 pi_write_block(cd->pi, cmd, 12);
402
403 return 0;
404}
405
406static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
407{
408 int r, d, p, n, k, j;
409
410 r = -1;
411 k = 0;
412 j = 0;
413
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;
421
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);
49b3a3cb
MS
434 if (verbose < 2)
435 printk_once(
436 "%s: WARNING: ATAPI phase errors\n",
437 cd->name);
1da177e4
LT
438 mdelay(1);
439 }
440 if (k++ > PCD_TMO) {
441 printk("%s: Stuck DRQ\n", cd->name);
442 break;
443 }
444 if (pcd_wait
445 (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
446 "completion")) {
447 r = -1;
448 break;
449 }
450 }
451 }
452
453 pi_disconnect(cd->pi);
454
455 return r;
456}
457
458static void pcd_req_sense(struct pcd_unit *cd, char *fun)
459{
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;
463
464 r = pcd_command(cd, rs_cmd, 16, "Request sense");
465 mdelay(1);
466 if (!r)
467 pcd_completion(cd, buf, "Request sense");
468
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);
478 }
479 if ((c == 2) || (c == 6))
480 cd->changed = 1;
481}
482
483static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
484{
485 int r;
486
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);
493
494 return r;
495}
496
497static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
498{
499 return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
500 "generic packet");
501}
502
503#define DBMSG(msg) ((verbose>1)?(msg):NULL)
504
505static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
506{
507 struct pcd_unit *cd = cdi->handle;
508 int res = cd->changed;
509 if (res)
510 cd->changed = 0;
511 return res;
512}
513
514static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
515{
516 char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
517
518 return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
519 lock ? "lock door" : "unlock door");
520}
521
522static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
523{
524 char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
525
526 return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
527 position ? "eject" : "close tray");
528}
529
530static void pcd_sleep(int cs)
531{
86e84862 532 schedule_timeout_interruptible(cs);
1da177e4
LT
533}
534
535static int pcd_reset(struct pcd_unit *cd)
536{
537 int i, k, flg;
538 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
539
540 pi_connect(cd->pi);
541 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
542 write_reg(cd, 7, 8);
543
544 pcd_sleep(20 * HZ / 1000); /* delay a bit */
545
546 k = 0;
547 while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
548 pcd_sleep(HZ / 10);
549
550 flg = 1;
551 for (i = 0; i < 5; i++)
552 flg &= (read_reg(cd, i + 1) == expect[i]);
553
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");
561 }
562
563 pi_disconnect(cd->pi);
564 return flg - 1;
565}
566
567static int pcd_drive_reset(struct cdrom_device_info *cdi)
568{
569 return pcd_reset(cdi->handle);
570}
571
572static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
573{
574 char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
575 int k, p;
576
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);
588 }
589 return 0x000020; /* timeout */
590}
591
592static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
593{
594 char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
595 struct pcd_unit *cd = cdi->handle;
596
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;
602}
603
604static int pcd_identify(struct pcd_unit *cd, char *id)
605{
606 int k, s;
607 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
608
609 pcd_bufblk = -1;
610
611 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
612
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;
620 }
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--;
627 }
628
629 printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
630
631 return 0;
632}
633
634/*
635 * returns 0, with id set if drive is detected
636 * -1, if drive detection failed
637 */
638static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
639{
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;
648 }
649 return -1;
650}
651
652static void pcd_probe_capabilities(void)
653{
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;
658
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;
678 }
679}
680
681static int pcd_detect(void)
682{
683 char id[18];
684 int k, unit;
685 struct pcd_unit *cd;
686
687 printk("%s: %s version %s, major %d, nice %d\n",
688 name, name, PCD_VERSION, major, nice);
689
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);
700 }
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);
715 }
716 }
717 if (k)
718 return 0;
719
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;
724}
725
726/* I/O request processing */
727static struct request_queue *pcd_queue;
728
165125e1 729static void do_pcd_request(struct request_queue * q)
1da177e4
LT
730{
731 if (pcd_busy)
732 return;
733 while (1) {
b12d4f82 734 if (!pcd_req) {
9934c8c0 735 pcd_req = blk_fetch_request(q);
b12d4f82
TH
736 if (!pcd_req)
737 return;
b12d4f82 738 }
1da177e4
LT
739
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;
83096ebf
TH
745 pcd_sector = blk_rq_pos(pcd_req);
746 pcd_count = blk_rq_cur_sectors(pcd_req);
1da177e4
LT
747 pcd_buf = pcd_req->buffer;
748 pcd_busy = 1;
749 ps_set_intr(do_pcd_read, NULL, 0, nice);
750 return;
b12d4f82
TH
751 } else {
752 __blk_end_request_all(pcd_req, -EIO);
753 pcd_req = NULL;
754 }
1da177e4
LT
755 }
756}
757
f06d9a2b 758static inline void next_request(int err)
1da177e4
LT
759{
760 unsigned long saved_flags;
761
762 spin_lock_irqsave(&pcd_lock, saved_flags);
b12d4f82
TH
763 if (!__blk_end_request_cur(pcd_req, err))
764 pcd_req = NULL;
1da177e4
LT
765 pcd_busy = 0;
766 do_pcd_request(pcd_queue);
767 spin_unlock_irqrestore(&pcd_lock, saved_flags);
768}
769
770static int pcd_ready(void)
771{
772 return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
773}
774
775static void pcd_transfer(void)
776{
777
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++;
784 }
785}
786
787static void pcd_start(void)
788{
789 int b, i;
790 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
791
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;
797 }
798
799 if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
800 pcd_bufblk = -1;
f06d9a2b 801 next_request(-EIO);
1da177e4
LT
802 return;
803 }
804
805 mdelay(1);
806
807 ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
808}
809
810static void do_pcd_read(void)
811{
812 pcd_busy = 1;
813 pcd_retries = 0;
814 pcd_transfer();
815 if (!pcd_count) {
f06d9a2b 816 next_request(0);
1da177e4
LT
817 return;
818 }
819
820 pi_do_claimed(pcd_current->pi, pcd_start);
821}
822
823static void do_pcd_read_drq(void)
824{
825 unsigned long saved_flags;
826
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;
833 }
834 pcd_bufblk = -1;
f06d9a2b 835 next_request(-EIO);
1da177e4
LT
836 return;
837 }
838
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);
843}
844
845/* the audio_ioctl stuff is adapted from sr_ioctl.c */
846
847static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
848{
849 struct pcd_unit *cd = cdi->handle;
850
851 switch (cmd) {
852
853 case CDROMREADTOCHDR:
854
855 {
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;
863
864 r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
865
866 tochdr->cdth_trk0 = buffer[2];
867 tochdr->cdth_trk1 = buffer[3];
868
869 return r ? -EIO : 0;
870 }
871
872 case CDROMREADTOCENTRY:
873
874 {
875 char cmd[12] =
876 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
877 0, 0, 0 };
878
879 struct cdrom_tocentry *tocentry =
880 (struct cdrom_tocentry *) arg;
881 unsigned char buffer[32];
882 int r;
883
884 cmd[1] =
885 (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
886 cmd[6] = tocentry->cdte_track;
887
888 r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
889
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];
902
903 return r ? -EIO : 0;
904 }
905
906 default:
907
908 return -ENOSYS;
909 }
910}
911
912static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
913{
914 char cmd[12] =
915 { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
916 char buffer[32];
917
918 if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
919 return -EIO;
920
921 memcpy(mcn->medium_catalog_number, buffer + 9, 13);
922 mcn->medium_catalog_number[13] = 0;
923
924 return 0;
925}
926
927static int __init pcd_init(void)
928{
929 struct pcd_unit *cd;
930 int unit;
931
932 if (disable)
8bca98ca 933 return -EINVAL;
1da177e4
LT
934
935 pcd_init_units();
936
937 if (pcd_detect())
8bca98ca 938 return -ENODEV;
1da177e4
LT
939
940 /* get the atapi capabilities page */
941 pcd_probe_capabilities();
942
943 if (register_blkdev(major, name)) {
944 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
945 put_disk(cd->disk);
8bca98ca 946 return -EBUSY;
1da177e4
LT
947 }
948
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);
8bca98ca 954 return -ENOMEM;
1da177e4
LT
955 }
956
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);
963 }
964 }
965
966 return 0;
967}
968
969static void __exit pcd_exit(void)
970{
971 struct pcd_unit *cd;
972 int unit;
973
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);
979 }
980 put_disk(cd->disk);
981 }
982 blk_cleanup_queue(pcd_queue);
983 unregister_blkdev(major, name);
984}
985
986MODULE_LICENSE("GPL");
987module_init(pcd_init)
988module_exit(pcd_exit)