blob: 8474a1b0740f6afcaa17bcd261bb2ff370997139 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Geert Uytterhoeven336ec132014-06-29 12:13:49 +020072 If this driver is built into the kernel, you can use the
73 following kernel command line parameters, with the same values
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 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>
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200141#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142#include <asm/uaccess.h>
143
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200144static DEFINE_MUTEX(pcd_mutex);
Alexey Dobriyan671d40f2007-04-23 14:41:07 -0700145static DEFINE_SPINLOCK(pcd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Rusty Russell1b9fbaf2012-01-13 09:32:26 +1030147module_param(verbose, int, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148module_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);
Tejun Heob1b56b92011-03-09 19:54:28 +0100175static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
176 unsigned int clearing, int slot_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
178static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
179static int pcd_drive_reset(struct cdrom_device_info *cdi);
180static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
181static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
182 unsigned int cmd, void *arg);
183static int pcd_packet(struct cdrom_device_info *cdi,
184 struct packet_command *cgc);
185
186static int pcd_detect(void);
187static void pcd_probe_capabilities(void);
188static void do_pcd_read_drq(void);
Jens Axboe165125e2007-07-24 09:28:11 +0200189static void do_pcd_request(struct request_queue * q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190static void do_pcd_read(void);
191
192struct 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
204static struct pcd_unit pcd[PCD_UNITS];
205
206static char pcd_scratch[64];
207static char pcd_buffer[2048]; /* raw block buffer */
208static 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
217static struct pcd_unit *pcd_current; /* current request's drive */
218static struct request *pcd_req;
219static int pcd_retries; /* retries on current request */
220static int pcd_busy; /* request being processed ? */
221static int pcd_sector; /* address of next requested sector */
222static int pcd_count; /* number of blocks still to do */
223static char *pcd_buf; /* buffer for request in progress */
Sudip Mukherjee9f4ba6b2015-05-20 20:57:01 +0530224static void *par_drv; /* reference of parport driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226/* kernel glue structures */
227
Al Viroc9acf902008-03-02 09:35:06 -0500228static int pcd_block_open(struct block_device *bdev, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229{
Al Viroc9acf902008-03-02 09:35:06 -0500230 struct pcd_unit *cd = bdev->bd_disk->private_data;
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200231 int ret;
232
Maurizio Lombardi94ee9a42018-03-09 13:59:06 +0100233 check_disk_change(bdev);
234
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200235 mutex_lock(&pcd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200236 ret = cdrom_open(&cd->info, bdev, mode);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200237 mutex_unlock(&pcd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200238
239 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240}
241
Al Virodb2a1442013-05-05 21:52:57 -0400242static void pcd_block_release(struct gendisk *disk, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
Al Viroc9acf902008-03-02 09:35:06 -0500244 struct pcd_unit *cd = disk->private_data;
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200245 mutex_lock(&pcd_mutex);
Al Viroc9acf902008-03-02 09:35:06 -0500246 cdrom_release(&cd->info, mode);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200247 mutex_unlock(&pcd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248}
249
Al Viroc9acf902008-03-02 09:35:06 -0500250static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 unsigned cmd, unsigned long arg)
252{
Al Viroc9acf902008-03-02 09:35:06 -0500253 struct pcd_unit *cd = bdev->bd_disk->private_data;
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200254 int ret;
255
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200256 mutex_lock(&pcd_mutex);
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200257 ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200258 mutex_unlock(&pcd_mutex);
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200259
260 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261}
262
Tejun Heob1b56b92011-03-09 19:54:28 +0100263static unsigned int pcd_block_check_events(struct gendisk *disk,
264 unsigned int clearing)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
266 struct pcd_unit *cd = disk->private_data;
Tejun Heob1b56b92011-03-09 19:54:28 +0100267 return cdrom_check_events(&cd->info, clearing);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268}
269
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700270static const struct block_device_operations pcd_bdops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 .owner = THIS_MODULE,
Al Viroc9acf902008-03-02 09:35:06 -0500272 .open = pcd_block_open,
273 .release = pcd_block_release,
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200274 .ioctl = pcd_block_ioctl,
Tejun Heob1b56b92011-03-09 19:54:28 +0100275 .check_events = pcd_block_check_events,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276};
277
278static struct cdrom_device_ops pcd_dops = {
279 .open = pcd_open,
280 .release = pcd_release,
281 .drive_status = pcd_drive_status,
Tejun Heob1b56b92011-03-09 19:54:28 +0100282 .check_events = pcd_check_events,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 .tray_move = pcd_tray_move,
284 .lock_door = pcd_lock_door,
285 .get_mcn = pcd_get_mcn,
286 .reset = pcd_drive_reset,
287 .audio_ioctl = pcd_audio_ioctl,
288 .generic_packet = pcd_packet,
289 .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
290 CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
291 CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
292 CDC_CD_RW,
293};
294
295static void pcd_init_units(void)
296{
297 struct pcd_unit *cd;
298 int unit;
299
300 pcd_drive_count = 0;
301 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
302 struct gendisk *disk = alloc_disk(1);
303 if (!disk)
304 continue;
305 cd->disk = disk;
306 cd->pi = &cd->pia;
307 cd->present = 0;
308 cd->last_sense = 0;
309 cd->changed = 1;
310 cd->drive = (*drives[unit])[D_SLV];
311 if ((*drives[unit])[D_PRT])
312 pcd_drive_count++;
313
314 cd->name = &cd->info.name[0];
315 snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
316 cd->info.ops = &pcd_dops;
317 cd->info.handle = cd;
318 cd->info.speed = 0;
319 cd->info.capacity = 1;
320 cd->info.mask = 0;
321 disk->major = major;
322 disk->first_minor = unit;
323 strcpy(disk->disk_name, cd->name); /* umm... */
324 disk->fops = &pcd_bdops;
Tejun Heod4dc2102011-04-21 20:54:46 +0200325 disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 }
327}
328
329static int pcd_open(struct cdrom_device_info *cdi, int purpose)
330{
331 struct pcd_unit *cd = cdi->handle;
332 if (!cd->present)
333 return -ENODEV;
334 return 0;
335}
336
337static void pcd_release(struct cdrom_device_info *cdi)
338{
339}
340
341static inline int status_reg(struct pcd_unit *cd)
342{
343 return pi_read_regr(cd->pi, 1, 6);
344}
345
346static inline int read_reg(struct pcd_unit *cd, int reg)
347{
348 return pi_read_regr(cd->pi, 0, reg);
349}
350
351static inline void write_reg(struct pcd_unit *cd, int reg, int val)
352{
353 pi_write_regr(cd->pi, 0, reg, val);
354}
355
356static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
357{
358 int j, r, e, s, p;
359
360 j = 0;
361 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
362 && (j++ < PCD_SPIN))
363 udelay(PCD_DELAY);
364
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800365 if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 s = read_reg(cd, 7);
367 e = read_reg(cd, 1);
368 p = read_reg(cd, 2);
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800369 if (j > PCD_SPIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 e |= 0x100;
371 if (fun)
372 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
373 " loop=%d phase=%d\n",
374 cd->name, fun, msg, r, s, e, j, p);
375 return (s << 8) + r;
376 }
377 return 0;
378}
379
380static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
381{
382 pi_connect(cd->pi);
383
384 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
385
386 if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
387 pi_disconnect(cd->pi);
388 return -1;
389 }
390
391 write_reg(cd, 4, dlen % 256);
392 write_reg(cd, 5, dlen / 256);
393 write_reg(cd, 7, 0xa0); /* ATAPI packet command */
394
395 if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
396 pi_disconnect(cd->pi);
397 return -1;
398 }
399
400 if (read_reg(cd, 2) != 1) {
401 printk("%s: %s: command phase error\n", cd->name, fun);
402 pi_disconnect(cd->pi);
403 return -1;
404 }
405
406 pi_write_block(cd->pi, cmd, 12);
407
408 return 0;
409}
410
411static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
412{
413 int r, d, p, n, k, j;
414
415 r = -1;
416 k = 0;
417 j = 0;
418
419 if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
420 fun, "completion")) {
421 r = 0;
422 while (read_reg(cd, 7) & IDE_DRQ) {
423 d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
424 n = (d + 3) & 0xfffc;
425 p = read_reg(cd, 2) & 3;
426
427 if ((p == 2) && (n > 0) && (j == 0)) {
428 pi_read_block(cd->pi, buf, n);
429 if (verbose > 1)
430 printk("%s: %s: Read %d bytes\n",
431 cd->name, fun, n);
432 r = 0;
433 j++;
434 } else {
435 if (verbose > 1)
436 printk
437 ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
438 cd->name, fun, p, d, k);
Marcin Slusarz49b3a3c2009-08-24 10:56:38 +0200439 if (verbose < 2)
440 printk_once(
441 "%s: WARNING: ATAPI phase errors\n",
442 cd->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 mdelay(1);
444 }
445 if (k++ > PCD_TMO) {
446 printk("%s: Stuck DRQ\n", cd->name);
447 break;
448 }
449 if (pcd_wait
450 (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
451 "completion")) {
452 r = -1;
453 break;
454 }
455 }
456 }
457
458 pi_disconnect(cd->pi);
459
460 return r;
461}
462
463static void pcd_req_sense(struct pcd_unit *cd, char *fun)
464{
465 char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
466 char buf[16];
467 int r, c;
468
469 r = pcd_command(cd, rs_cmd, 16, "Request sense");
470 mdelay(1);
471 if (!r)
472 pcd_completion(cd, buf, "Request sense");
473
474 cd->last_sense = -1;
475 c = 2;
476 if (!r) {
477 if (fun)
478 printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
479 cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
480 c = buf[2] & 0xf;
481 cd->last_sense =
482 c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
483 }
484 if ((c == 2) || (c == 6))
485 cd->changed = 1;
486}
487
488static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
489{
490 int r;
491
492 r = pcd_command(cd, cmd, dlen, fun);
493 mdelay(1);
494 if (!r)
495 r = pcd_completion(cd, buf, fun);
496 if (r)
497 pcd_req_sense(cd, fun);
498
499 return r;
500}
501
502static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)
503{
504 return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
505 "generic packet");
506}
507
508#define DBMSG(msg) ((verbose>1)?(msg):NULL)
509
Tejun Heob1b56b92011-03-09 19:54:28 +0100510static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
511 unsigned int clearing, int slot_nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
513 struct pcd_unit *cd = cdi->handle;
514 int res = cd->changed;
515 if (res)
516 cd->changed = 0;
Tejun Heob1b56b92011-03-09 19:54:28 +0100517 return res ? DISK_EVENT_MEDIA_CHANGE : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
520static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
521{
522 char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
523
524 return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
525 lock ? "lock door" : "unlock door");
526}
527
528static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
529{
530 char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
531
532 return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
533 position ? "eject" : "close tray");
534}
535
536static void pcd_sleep(int cs)
537{
Nishanth Aravamudan86e84862005-09-10 00:27:28 -0700538 schedule_timeout_interruptible(cs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539}
540
541static int pcd_reset(struct pcd_unit *cd)
542{
543 int i, k, flg;
544 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
545
546 pi_connect(cd->pi);
547 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
548 write_reg(cd, 7, 8);
549
550 pcd_sleep(20 * HZ / 1000); /* delay a bit */
551
552 k = 0;
553 while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
554 pcd_sleep(HZ / 10);
555
556 flg = 1;
557 for (i = 0; i < 5; i++)
558 flg &= (read_reg(cd, i + 1) == expect[i]);
559
560 if (verbose) {
561 printk("%s: Reset (%d) signature = ", cd->name, k);
562 for (i = 0; i < 5; i++)
563 printk("%3x", read_reg(cd, i + 1));
564 if (!flg)
565 printk(" (incorrect)");
566 printk("\n");
567 }
568
569 pi_disconnect(cd->pi);
570 return flg - 1;
571}
572
573static int pcd_drive_reset(struct cdrom_device_info *cdi)
574{
575 return pcd_reset(cdi->handle);
576}
577
578static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
579{
580 char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
581 int k, p;
582
583 k = 0;
584 while (k < tmo) {
585 cd->last_sense = 0;
586 pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
587 p = cd->last_sense;
588 if (!p)
589 return 0;
590 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
591 return p;
592 k++;
593 pcd_sleep(HZ);
594 }
595 return 0x000020; /* timeout */
596}
597
598static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
599{
600 char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
601 struct pcd_unit *cd = cdi->handle;
602
603 if (pcd_ready_wait(cd, PCD_READY_TMO))
604 return CDS_DRIVE_NOT_READY;
605 if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
606 return CDS_NO_DISC;
607 return CDS_DISC_OK;
608}
609
610static int pcd_identify(struct pcd_unit *cd, char *id)
611{
612 int k, s;
613 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
614
615 pcd_bufblk = -1;
616
617 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
618
619 if (s)
620 return -1;
621 if ((pcd_buffer[0] & 0x1f) != 5) {
622 if (verbose)
623 printk("%s: %s is not a CD-ROM\n",
624 cd->name, cd->drive ? "Slave" : "Master");
625 return -1;
626 }
627 memcpy(id, pcd_buffer + 16, 16);
628 id[16] = 0;
629 k = 16;
630 while ((k >= 0) && (id[k] <= 0x20)) {
631 id[k] = 0;
632 k--;
633 }
634
635 printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
636
637 return 0;
638}
639
640/*
641 * returns 0, with id set if drive is detected
642 * -1, if drive detection failed
643 */
644static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
645{
646 if (ms == -1) {
647 for (cd->drive = 0; cd->drive <= 1; cd->drive++)
648 if (!pcd_reset(cd) && !pcd_identify(cd, id))
649 return 0;
650 } else {
651 cd->drive = ms;
652 if (!pcd_reset(cd) && !pcd_identify(cd, id))
653 return 0;
654 }
655 return -1;
656}
657
658static void pcd_probe_capabilities(void)
659{
660 int unit, r;
661 char buffer[32];
662 char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
663 struct pcd_unit *cd;
664
665 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
666 if (!cd->present)
667 continue;
668 r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
669 if (r)
670 continue;
671 /* we should now have the cap page */
672 if ((buffer[11] & 1) == 0)
673 cd->info.mask |= CDC_CD_R;
674 if ((buffer[11] & 2) == 0)
675 cd->info.mask |= CDC_CD_RW;
676 if ((buffer[12] & 1) == 0)
677 cd->info.mask |= CDC_PLAY_AUDIO;
678 if ((buffer[14] & 1) == 0)
679 cd->info.mask |= CDC_LOCK;
680 if ((buffer[14] & 8) == 0)
681 cd->info.mask |= CDC_OPEN_TRAY;
682 if ((buffer[14] >> 6) == 0)
683 cd->info.mask |= CDC_CLOSE_TRAY;
684 }
685}
686
687static int pcd_detect(void)
688{
689 char id[18];
690 int k, unit;
691 struct pcd_unit *cd;
692
693 printk("%s: %s version %s, major %d, nice %d\n",
694 name, name, PCD_VERSION, major, nice);
695
Sudip Mukherjee9f4ba6b2015-05-20 20:57:01 +0530696 par_drv = pi_register_driver(name);
697 if (!par_drv) {
698 pr_err("failed to register %s driver\n", name);
699 return -1;
700 }
701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 k = 0;
703 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
704 cd = pcd;
705 if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
706 PI_PCD, verbose, cd->name)) {
707 if (!pcd_probe(cd, -1, id) && cd->disk) {
708 cd->present = 1;
709 k++;
710 } else
711 pi_release(cd->pi);
712 }
713 } else {
714 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
715 int *conf = *drives[unit];
716 if (!conf[D_PRT])
717 continue;
718 if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
719 conf[D_UNI], conf[D_PRO], conf[D_DLY],
720 pcd_buffer, PI_PCD, verbose, cd->name))
721 continue;
722 if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {
723 cd->present = 1;
724 k++;
725 } else
726 pi_release(cd->pi);
727 }
728 }
729 if (k)
730 return 0;
731
732 printk("%s: No CD-ROM drive found\n", name);
733 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
734 put_disk(cd->disk);
Sudip Mukherjee9f4ba6b2015-05-20 20:57:01 +0530735 pi_unregister_driver(par_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return -1;
737}
738
739/* I/O request processing */
740static struct request_queue *pcd_queue;
741
Jens Axboe165125e2007-07-24 09:28:11 +0200742static void do_pcd_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
744 if (pcd_busy)
745 return;
746 while (1) {
Tejun Heob12d4f82009-05-08 11:54:06 +0900747 if (!pcd_req) {
Tejun Heo9934c8c2009-05-08 11:54:16 +0900748 pcd_req = blk_fetch_request(q);
Tejun Heob12d4f82009-05-08 11:54:06 +0900749 if (!pcd_req)
750 return;
Tejun Heob12d4f82009-05-08 11:54:06 +0900751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 if (rq_data_dir(pcd_req) == READ) {
754 struct pcd_unit *cd = pcd_req->rq_disk->private_data;
755 if (cd != pcd_current)
756 pcd_bufblk = -1;
757 pcd_current = cd;
Tejun Heo83096eb2009-05-07 22:24:39 +0900758 pcd_sector = blk_rq_pos(pcd_req);
759 pcd_count = blk_rq_cur_sectors(pcd_req);
Jens Axboeb4f42e22014-04-10 09:46:28 -0600760 pcd_buf = bio_data(pcd_req->bio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 pcd_busy = 1;
762 ps_set_intr(do_pcd_read, NULL, 0, nice);
763 return;
Tejun Heob12d4f82009-05-08 11:54:06 +0900764 } else {
765 __blk_end_request_all(pcd_req, -EIO);
766 pcd_req = NULL;
767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769}
770
Tejun Heof06d9a22009-04-23 11:05:19 +0900771static inline void next_request(int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 unsigned long saved_flags;
774
775 spin_lock_irqsave(&pcd_lock, saved_flags);
Tejun Heob12d4f82009-05-08 11:54:06 +0900776 if (!__blk_end_request_cur(pcd_req, err))
777 pcd_req = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 pcd_busy = 0;
779 do_pcd_request(pcd_queue);
780 spin_unlock_irqrestore(&pcd_lock, saved_flags);
781}
782
783static int pcd_ready(void)
784{
785 return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
786}
787
788static void pcd_transfer(void)
789{
790
791 while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
792 int o = (pcd_sector % 4) * 512;
793 memcpy(pcd_buf, pcd_buffer + o, 512);
794 pcd_count--;
795 pcd_buf += 512;
796 pcd_sector++;
797 }
798}
799
800static void pcd_start(void)
801{
802 int b, i;
803 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
804
805 pcd_bufblk = pcd_sector / 4;
806 b = pcd_bufblk;
807 for (i = 0; i < 4; i++) {
808 rd_cmd[5 - i] = b & 0xff;
809 b = b >> 8;
810 }
811
812 if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
813 pcd_bufblk = -1;
Tejun Heof06d9a22009-04-23 11:05:19 +0900814 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 return;
816 }
817
818 mdelay(1);
819
820 ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
821}
822
823static void do_pcd_read(void)
824{
825 pcd_busy = 1;
826 pcd_retries = 0;
827 pcd_transfer();
828 if (!pcd_count) {
Tejun Heof06d9a22009-04-23 11:05:19 +0900829 next_request(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 return;
831 }
832
833 pi_do_claimed(pcd_current->pi, pcd_start);
834}
835
836static void do_pcd_read_drq(void)
837{
838 unsigned long saved_flags;
839
840 if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
841 if (pcd_retries < PCD_RETRIES) {
842 mdelay(1);
843 pcd_retries++;
844 pi_do_claimed(pcd_current->pi, pcd_start);
845 return;
846 }
847 pcd_bufblk = -1;
Tejun Heof06d9a22009-04-23 11:05:19 +0900848 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 return;
850 }
851
852 do_pcd_read();
853 spin_lock_irqsave(&pcd_lock, saved_flags);
854 do_pcd_request(pcd_queue);
855 spin_unlock_irqrestore(&pcd_lock, saved_flags);
856}
857
858/* the audio_ioctl stuff is adapted from sr_ioctl.c */
859
860static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
861{
862 struct pcd_unit *cd = cdi->handle;
863
864 switch (cmd) {
865
866 case CDROMREADTOCHDR:
867
868 {
869 char cmd[12] =
870 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
871 0, 0, 0 };
872 struct cdrom_tochdr *tochdr =
873 (struct cdrom_tochdr *) arg;
874 char buffer[32];
875 int r;
876
877 r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
878
879 tochdr->cdth_trk0 = buffer[2];
880 tochdr->cdth_trk1 = buffer[3];
881
882 return r ? -EIO : 0;
883 }
884
885 case CDROMREADTOCENTRY:
886
887 {
888 char cmd[12] =
889 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
890 0, 0, 0 };
891
892 struct cdrom_tocentry *tocentry =
893 (struct cdrom_tocentry *) arg;
894 unsigned char buffer[32];
895 int r;
896
897 cmd[1] =
898 (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
899 cmd[6] = tocentry->cdte_track;
900
901 r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
902
903 tocentry->cdte_ctrl = buffer[5] & 0xf;
904 tocentry->cdte_adr = buffer[5] >> 4;
905 tocentry->cdte_datamode =
906 (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
907 if (tocentry->cdte_format == CDROM_MSF) {
908 tocentry->cdte_addr.msf.minute = buffer[9];
909 tocentry->cdte_addr.msf.second = buffer[10];
910 tocentry->cdte_addr.msf.frame = buffer[11];
911 } else
912 tocentry->cdte_addr.lba =
913 (((((buffer[8] << 8) + buffer[9]) << 8)
914 + buffer[10]) << 8) + buffer[11];
915
916 return r ? -EIO : 0;
917 }
918
919 default:
920
921 return -ENOSYS;
922 }
923}
924
925static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
926{
927 char cmd[12] =
928 { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
929 char buffer[32];
930
931 if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
932 return -EIO;
933
934 memcpy(mcn->medium_catalog_number, buffer + 9, 13);
935 mcn->medium_catalog_number[13] = 0;
936
937 return 0;
938}
939
940static int __init pcd_init(void)
941{
942 struct pcd_unit *cd;
943 int unit;
944
945 if (disable)
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800946 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 pcd_init_units();
949
950 if (pcd_detect())
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800951 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
953 /* get the atapi capabilities page */
954 pcd_probe_capabilities();
955
956 if (register_blkdev(major, name)) {
957 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
958 put_disk(cd->disk);
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800959 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961
962 pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
963 if (!pcd_queue) {
964 unregister_blkdev(major, name);
965 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
966 put_disk(cd->disk);
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800967 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 }
969
970 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
971 if (cd->present) {
972 register_cdrom(&cd->info);
973 cd->disk->private_data = cd;
974 cd->disk->queue = pcd_queue;
975 add_disk(cd->disk);
976 }
977 }
978
979 return 0;
980}
981
982static void __exit pcd_exit(void)
983{
984 struct pcd_unit *cd;
985 int unit;
986
987 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
988 if (cd->present) {
989 del_gendisk(cd->disk);
990 pi_release(cd->pi);
991 unregister_cdrom(&cd->info);
992 }
993 put_disk(cd->disk);
994 }
995 blk_cleanup_queue(pcd_queue);
996 unregister_blkdev(major, name);
Sudip Mukherjee9f4ba6b2015-05-20 20:57:01 +0530997 pi_unregister_driver(par_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998}
999
1000MODULE_LICENSE("GPL");
1001module_init(pcd_init)
1002module_exit(pcd_exit)