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