blob: 38b4d566b81602f6899a5ed666288e80891c3f04 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU General Public License.
4
5 This is the high-level driver for parallel port ATAPI disk
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 disk drive, but if their individual parameters are
10 specified, the driver can handle up to 4 drives.
11
12 The behaviour of the pf 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-7 integers as follows:
18 drive2
19 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<lun>,<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 CDroms 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 <lun> Some ATAPI devices support multiple LUNs.
47 One example is the ATAPI PD/CD drive from
48 Matshita/Panasonic. This device has a
49 CD drive on LUN 0 and a PD drive on LUN 1.
50 By default, the driver will search for the
51 first LUN with a supported device. Set
52 this parameter to force it to use a specific
53 LUN. (default -1)
54
55 <dly> some parallel ports require the driver to
56 go more slowly. -1 sets a default value that
57 should work with the chosen protocol. Otherwise,
58 set this to a small integer, the larger it is
59 the slower the port i/o. In some cases, setting
60 this to zero will speed up the device. (default -1)
61
62 major You may use this parameter to overide the
63 default major number (47) that this driver
64 will use. Be sure to change the device
65 name as well.
66
67 name This parameter is a character string that
68 contains the name the kernel will use for this
69 device (in /proc output, for instance).
70 (default "pf").
71
72 cluster The driver will attempt to aggregate requests
73 for adjacent blocks into larger multi-block
74 clusters. The maximum cluster size (in 512
75 byte sectors) is set with this parameter.
76 (default 64)
77
78 verbose This parameter controls the amount of logging
79 that the driver will do. Set it to 0 for
80 normal operation, 1 to see autoprobe progress
81 messages, or 2 to see additional debugging
82 output. (default 0)
83
84 nice This parameter controls the driver's use of
85 idle CPU time, at the expense of some speed.
86
87 If this driver is built into the kernel, you can use the
88 following command line parameters, with the same values
89 as the corresponding module parameters listed above:
90
91 pf.drive0
92 pf.drive1
93 pf.drive2
94 pf.drive3
95 pf.cluster
96 pf.nice
97
98 In addition, you can use the parameter pf.disable to disable
99 the driver entirely.
100
101*/
102
103/* Changes:
104
105 1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti().
106 Fix for drives that don't clear STAT_ERR
107 until after next CDB delivered.
108 Small change in pf_completion to round
109 up transfer size.
110 1.02 GRG 1998.06.16 Eliminated an Ugh
111 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging
112 1.04 GRG 1998.09.24 Added jumbo support
113
114*/
115
116#define PF_VERSION "1.04"
117#define PF_MAJOR 47
118#define PF_NAME "pf"
119#define PF_UNITS 4
120
121/* Here are things one can override from the insmod command.
122 Most are autoprobed by paride unless set here. Verbose is off
123 by default.
124
125*/
126
127static int verbose = 0;
128static int major = PF_MAJOR;
129static char *name = PF_NAME;
130static int cluster = 64;
131static int nice = 0;
132static int disable = 0;
133
134static int drive0[7] = { 0, 0, 0, -1, -1, -1, -1 };
135static int drive1[7] = { 0, 0, 0, -1, -1, -1, -1 };
136static int drive2[7] = { 0, 0, 0, -1, -1, -1, -1 };
137static int drive3[7] = { 0, 0, 0, -1, -1, -1, -1 };
138
139static int (*drives[4])[7] = {&drive0, &drive1, &drive2, &drive3};
140static int pf_drive_count;
141
142enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
143
144/* end of parameters */
145
146#include <linux/module.h>
147#include <linux/init.h>
148#include <linux/fs.h>
149#include <linux/delay.h>
150#include <linux/hdreg.h>
151#include <linux/cdrom.h>
152#include <linux/spinlock.h>
153#include <linux/blkdev.h>
154#include <linux/blkpg.h>
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200155#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156#include <asm/uaccess.h>
157
Alexey Dobriyan671d40f2007-04-23 14:41:07 -0700158static DEFINE_SPINLOCK(pf_spin_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160module_param(verbose, bool, 0644);
161module_param(major, int, 0);
162module_param(name, charp, 0);
163module_param(cluster, int, 0);
164module_param(nice, int, 0);
165module_param_array(drive0, int, NULL, 0);
166module_param_array(drive1, int, NULL, 0);
167module_param_array(drive2, int, NULL, 0);
168module_param_array(drive3, int, NULL, 0);
169
170#include "paride.h"
171#include "pseudo.h"
172
173/* constants for faking geometry numbers */
174
175#define PF_FD_MAX 8192 /* use FD geometry under this size */
176#define PF_FD_HDS 2
177#define PF_FD_SPT 18
178#define PF_HD_HDS 64
179#define PF_HD_SPT 32
180
181#define PF_MAX_RETRIES 5
182#define PF_TMO 800 /* interrupt timeout in jiffies */
183#define PF_SPIN_DEL 50 /* spin delay in micro-seconds */
184
185#define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)
186
187#define STAT_ERR 0x00001
188#define STAT_INDEX 0x00002
189#define STAT_ECC 0x00004
190#define STAT_DRQ 0x00008
191#define STAT_SEEK 0x00010
192#define STAT_WRERR 0x00020
193#define STAT_READY 0x00040
194#define STAT_BUSY 0x00080
195
196#define ATAPI_REQ_SENSE 0x03
197#define ATAPI_LOCK 0x1e
198#define ATAPI_DOOR 0x1b
199#define ATAPI_MODE_SENSE 0x5a
200#define ATAPI_CAPACITY 0x25
201#define ATAPI_IDENTIFY 0x12
202#define ATAPI_READ_10 0x28
203#define ATAPI_WRITE_10 0x2a
204
Al Viro8cfc7ca2008-03-02 09:36:16 -0500205static int pf_open(struct block_device *bdev, fmode_t mode);
Jens Axboe165125e2007-07-24 09:28:11 +0200206static void do_pf_request(struct request_queue * q);
Al Viro8cfc7ca2008-03-02 09:36:16 -0500207static int pf_ioctl(struct block_device *bdev, fmode_t mode,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 unsigned int cmd, unsigned long arg);
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800209static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Al Viro8cfc7ca2008-03-02 09:36:16 -0500211static int pf_release(struct gendisk *disk, fmode_t mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213static int pf_detect(void);
214static void do_pf_read(void);
215static void do_pf_read_start(void);
216static void do_pf_write(void);
217static void do_pf_write_start(void);
218static void do_pf_read_drq(void);
219static void do_pf_write_done(void);
220
221#define PF_NM 0
222#define PF_RO 1
223#define PF_RW 2
224
225#define PF_NAMELEN 8
226
227struct pf_unit {
228 struct pi_adapter pia; /* interface to paride layer */
229 struct pi_adapter *pi;
230 int removable; /* removable media device ? */
231 int media_status; /* media present ? WP ? */
232 int drive; /* drive */
233 int lun;
234 int access; /* count of active opens ... */
235 int present; /* device present ? */
236 char name[PF_NAMELEN]; /* pf0, pf1, ... */
237 struct gendisk *disk;
238};
239
240static struct pf_unit units[PF_UNITS];
241
242static int pf_identify(struct pf_unit *pf);
243static void pf_lock(struct pf_unit *pf, int func);
244static void pf_eject(struct pf_unit *pf);
245static int pf_check_media(struct gendisk *disk);
246
247static char pf_scratch[512]; /* scratch block buffer */
248
249/* the variables below are used mainly in the I/O request engine, which
250 processes only one request at a time.
251*/
252
253static int pf_retries = 0; /* i/o error retry count */
254static int pf_busy = 0; /* request being processed ? */
255static struct request *pf_req; /* current request */
256static int pf_block; /* address of next requested block */
257static int pf_count; /* number of blocks still to do */
258static int pf_run; /* sectors in current cluster */
259static int pf_cmd; /* current command READ/WRITE */
260static struct pf_unit *pf_current;/* unit of current request */
261static int pf_mask; /* stopper for pseudo-int */
262static char *pf_buf; /* buffer for request in progress */
263
264/* kernel glue structures */
265
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700266static const struct block_device_operations pf_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 .owner = THIS_MODULE,
Al Viro8cfc7ca2008-03-02 09:36:16 -0500268 .open = pf_open,
269 .release = pf_release,
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200270 .ioctl = pf_ioctl,
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800271 .getgeo = pf_getgeo,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 .media_changed = pf_check_media,
273};
274
275static void __init pf_init_units(void)
276{
277 struct pf_unit *pf;
278 int unit;
279
280 pf_drive_count = 0;
281 for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
282 struct gendisk *disk = alloc_disk(1);
283 if (!disk)
284 continue;
285 pf->disk = disk;
286 pf->pi = &pf->pia;
287 pf->media_status = PF_NM;
288 pf->drive = (*drives[unit])[D_SLV];
289 pf->lun = (*drives[unit])[D_LUN];
290 snprintf(pf->name, PF_NAMELEN, "%s%d", name, unit);
291 disk->major = major;
292 disk->first_minor = unit;
293 strcpy(disk->disk_name, pf->name);
294 disk->fops = &pf_fops;
295 if (!(*drives[unit])[D_PRT])
296 pf_drive_count++;
297 }
298}
299
Al Viro8cfc7ca2008-03-02 09:36:16 -0500300static int pf_open(struct block_device *bdev, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
Al Viro8cfc7ca2008-03-02 09:36:16 -0500302 struct pf_unit *pf = bdev->bd_disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304 pf_identify(pf);
305
306 if (pf->media_status == PF_NM)
307 return -ENODEV;
308
Al Viro8cfc7ca2008-03-02 09:36:16 -0500309 if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 return -EROFS;
311
312 pf->access++;
313 if (pf->removable)
314 pf_lock(pf, 1);
315
316 return 0;
317}
318
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800319static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
320{
321 struct pf_unit *pf = bdev->bd_disk->private_data;
322 sector_t capacity = get_capacity(pf->disk);
323
324 if (capacity < PF_FD_MAX) {
325 geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
326 geo->heads = PF_FD_HDS;
327 geo->sectors = PF_FD_SPT;
328 } else {
329 geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
330 geo->heads = PF_HD_HDS;
331 geo->sectors = PF_HD_SPT;
332 }
333
334 return 0;
335}
336
Al Viro8cfc7ca2008-03-02 09:36:16 -0500337static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
Al Viro8cfc7ca2008-03-02 09:36:16 -0500339 struct pf_unit *pf = bdev->bd_disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800341 if (cmd != CDROMEJECT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 return -EINVAL;
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800343
344 if (pf->access != 1)
345 return -EBUSY;
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200346 lock_kernel();
Christoph Hellwiga885c8c2006-01-08 01:02:50 -0800347 pf_eject(pf);
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200348 unlock_kernel();
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 return 0;
351}
352
Al Viro8cfc7ca2008-03-02 09:36:16 -0500353static int pf_release(struct gendisk *disk, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Al Viro8cfc7ca2008-03-02 09:36:16 -0500355 struct pf_unit *pf = disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 if (pf->access <= 0)
358 return -EINVAL;
359
360 pf->access--;
361
362 if (!pf->access && pf->removable)
363 pf_lock(pf, 0);
364
365 return 0;
366
367}
368
369static int pf_check_media(struct gendisk *disk)
370{
371 return 1;
372}
373
374static inline int status_reg(struct pf_unit *pf)
375{
376 return pi_read_regr(pf->pi, 1, 6);
377}
378
379static inline int read_reg(struct pf_unit *pf, int reg)
380{
381 return pi_read_regr(pf->pi, 0, reg);
382}
383
384static inline void write_reg(struct pf_unit *pf, int reg, int val)
385{
386 pi_write_regr(pf->pi, 0, reg, val);
387}
388
389static int pf_wait(struct pf_unit *pf, int go, int stop, char *fun, char *msg)
390{
391 int j, r, e, s, p;
392
393 j = 0;
394 while ((((r = status_reg(pf)) & go) || (stop && (!(r & stop))))
395 && (j++ < PF_SPIN))
396 udelay(PF_SPIN_DEL);
397
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800398 if ((r & (STAT_ERR & stop)) || (j > PF_SPIN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 s = read_reg(pf, 7);
400 e = read_reg(pf, 1);
401 p = read_reg(pf, 2);
Roel Kluinc12ec0a2010-03-11 14:09:47 -0800402 if (j > PF_SPIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 e |= 0x100;
404 if (fun)
405 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
406 " loop=%d phase=%d\n",
407 pf->name, fun, msg, r, s, e, j, p);
408 return (e << 8) + s;
409 }
410 return 0;
411}
412
413static int pf_command(struct pf_unit *pf, char *cmd, int dlen, char *fun)
414{
415 pi_connect(pf->pi);
416
417 write_reg(pf, 6, 0xa0+0x10*pf->drive);
418
419 if (pf_wait(pf, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
420 pi_disconnect(pf->pi);
421 return -1;
422 }
423
424 write_reg(pf, 4, dlen % 256);
425 write_reg(pf, 5, dlen / 256);
426 write_reg(pf, 7, 0xa0); /* ATAPI packet command */
427
428 if (pf_wait(pf, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
429 pi_disconnect(pf->pi);
430 return -1;
431 }
432
433 if (read_reg(pf, 2) != 1) {
434 printk("%s: %s: command phase error\n", pf->name, fun);
435 pi_disconnect(pf->pi);
436 return -1;
437 }
438
439 pi_write_block(pf->pi, cmd, 12);
440
441 return 0;
442}
443
444static int pf_completion(struct pf_unit *pf, char *buf, char *fun)
445{
446 int r, s, n;
447
448 r = pf_wait(pf, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
449 fun, "completion");
450
451 if ((read_reg(pf, 2) & 2) && (read_reg(pf, 7) & STAT_DRQ)) {
452 n = (((read_reg(pf, 4) + 256 * read_reg(pf, 5)) +
453 3) & 0xfffc);
454 pi_read_block(pf->pi, buf, n);
455 }
456
457 s = pf_wait(pf, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
458
459 pi_disconnect(pf->pi);
460
461 return (r ? r : s);
462}
463
464static void pf_req_sense(struct pf_unit *pf, int quiet)
465{
466 char rs_cmd[12] =
467 { ATAPI_REQ_SENSE, pf->lun << 5, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
468 char buf[16];
469 int r;
470
471 r = pf_command(pf, rs_cmd, 16, "Request sense");
472 mdelay(1);
473 if (!r)
474 pf_completion(pf, buf, "Request sense");
475
476 if ((!r) && (!quiet))
477 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
478 pf->name, buf[2] & 0xf, buf[12], buf[13]);
479}
480
481static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fun)
482{
483 int r;
484
485 r = pf_command(pf, cmd, dlen, fun);
486 mdelay(1);
487 if (!r)
488 r = pf_completion(pf, buf, fun);
489 if (r)
490 pf_req_sense(pf, !fun);
491
492 return r;
493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495static void pf_lock(struct pf_unit *pf, int func)
496{
497 char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
498
Ondrej Zarye62aa042007-11-14 16:59:24 -0800499 pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
501
502static void pf_eject(struct pf_unit *pf)
503{
504 char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
505
506 pf_lock(pf, 0);
507 pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject");
508}
509
510#define PF_RESET_TMO 30 /* in tenths of a second */
511
512static void pf_sleep(int cs)
513{
Nishanth Aravamudan86e84862005-09-10 00:27:28 -0700514 schedule_timeout_interruptible(cs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515}
516
517/* the ATAPI standard actually specifies the contents of all 7 registers
518 after a reset, but the specification is ambiguous concerning the last
519 two bytes, and different drives interpret the standard differently.
520 */
521
522static int pf_reset(struct pf_unit *pf)
523{
524 int i, k, flg;
525 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
526
527 pi_connect(pf->pi);
528 write_reg(pf, 6, 0xa0+0x10*pf->drive);
529 write_reg(pf, 7, 8);
530
531 pf_sleep(20 * HZ / 1000);
532
533 k = 0;
534 while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY))
535 pf_sleep(HZ / 10);
536
537 flg = 1;
538 for (i = 0; i < 5; i++)
539 flg &= (read_reg(pf, i + 1) == expect[i]);
540
541 if (verbose) {
542 printk("%s: Reset (%d) signature = ", pf->name, k);
543 for (i = 0; i < 5; i++)
544 printk("%3x", read_reg(pf, i + 1));
545 if (!flg)
546 printk(" (incorrect)");
547 printk("\n");
548 }
549
550 pi_disconnect(pf->pi);
551 return flg - 1;
552}
553
554static void pf_mode_sense(struct pf_unit *pf)
555{
556 char ms_cmd[12] =
557 { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
558 char buf[8];
559
Ondrej Zarye62aa042007-11-14 16:59:24 -0800560 pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 pf->media_status = PF_RW;
562 if (buf[3] & 0x80)
563 pf->media_status = PF_RO;
564}
565
566static void xs(char *buf, char *targ, int offs, int len)
567{
568 int j, k, l;
569
570 j = 0;
571 l = 0;
572 for (k = 0; k < len; k++)
573 if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
574 l = targ[j++] = buf[k + offs];
575 if (l == 0x20)
576 j--;
577 targ[j] = 0;
578}
579
580static int xl(char *buf, int offs)
581{
582 int v, k;
583
584 v = 0;
585 for (k = 0; k < 4; k++)
586 v = v * 256 + (buf[k + offs] & 0xff);
587 return v;
588}
589
590static void pf_get_capacity(struct pf_unit *pf)
591{
592 char rc_cmd[12] = { ATAPI_CAPACITY, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
593 char buf[8];
594 int bs;
595
Ondrej Zarye62aa042007-11-14 16:59:24 -0800596 if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 pf->media_status = PF_NM;
598 return;
599 }
600 set_capacity(pf->disk, xl(buf, 0) + 1);
601 bs = xl(buf, 4);
602 if (bs != 512) {
603 set_capacity(pf->disk, 0);
604 if (verbose)
605 printk("%s: Drive %d, LUN %d,"
606 " unsupported block size %d\n",
607 pf->name, pf->drive, pf->lun, bs);
608 }
609}
610
611static int pf_identify(struct pf_unit *pf)
612{
613 int dt, s;
614 char *ms[2] = { "master", "slave" };
615 char mf[10], id[18];
616 char id_cmd[12] =
617 { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
618 char buf[36];
619
620 s = pf_atapi(pf, id_cmd, 36, buf, "identify");
621 if (s)
622 return -1;
623
624 dt = buf[0] & 0x1f;
625 if ((dt != 0) && (dt != 7)) {
626 if (verbose)
627 printk("%s: Drive %d, LUN %d, unsupported type %d\n",
628 pf->name, pf->drive, pf->lun, dt);
629 return -1;
630 }
631
632 xs(buf, mf, 8, 8);
633 xs(buf, id, 16, 16);
634
635 pf->removable = (buf[1] & 0x80);
636
637 pf_mode_sense(pf);
638 pf_mode_sense(pf);
639 pf_mode_sense(pf);
640
641 pf_get_capacity(pf);
642
643 printk("%s: %s %s, %s LUN %d, type %d",
644 pf->name, mf, id, ms[pf->drive], pf->lun, dt);
645 if (pf->removable)
646 printk(", removable");
647 if (pf->media_status == PF_NM)
648 printk(", no media\n");
649 else {
650 if (pf->media_status == PF_RO)
651 printk(", RO");
652 printk(", %llu blocks\n",
653 (unsigned long long)get_capacity(pf->disk));
654 }
655 return 0;
656}
657
658/* returns 0, with id set if drive is detected
659 -1, if drive detection failed
660*/
661static int pf_probe(struct pf_unit *pf)
662{
663 if (pf->drive == -1) {
664 for (pf->drive = 0; pf->drive <= 1; pf->drive++)
665 if (!pf_reset(pf)) {
666 if (pf->lun != -1)
667 return pf_identify(pf);
668 else
669 for (pf->lun = 0; pf->lun < 8; pf->lun++)
670 if (!pf_identify(pf))
671 return 0;
672 }
673 } else {
674 if (pf_reset(pf))
675 return -1;
676 if (pf->lun != -1)
677 return pf_identify(pf);
678 for (pf->lun = 0; pf->lun < 8; pf->lun++)
679 if (!pf_identify(pf))
680 return 0;
681 }
682 return -1;
683}
684
685static int pf_detect(void)
686{
687 struct pf_unit *pf = units;
688 int k, unit;
689
690 printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
691 name, name, PF_VERSION, major, cluster, nice);
692
693 k = 0;
694 if (pf_drive_count == 0) {
695 if (pi_init(pf->pi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF,
696 verbose, pf->name)) {
697 if (!pf_probe(pf) && pf->disk) {
698 pf->present = 1;
699 k++;
700 } else
701 pi_release(pf->pi);
702 }
703
704 } else
705 for (unit = 0; unit < PF_UNITS; unit++, pf++) {
706 int *conf = *drives[unit];
707 if (!conf[D_PRT])
708 continue;
709 if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD],
710 conf[D_UNI], conf[D_PRO], conf[D_DLY],
711 pf_scratch, PI_PF, verbose, pf->name)) {
Eric Sesterhenn8e53cfc2006-06-29 02:24:32 -0700712 if (pf->disk && !pf_probe(pf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 pf->present = 1;
714 k++;
715 } else
716 pi_release(pf->pi);
717 }
718 }
719 if (k)
720 return 0;
721
722 printk("%s: No ATAPI disk detected\n", name);
723 for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
724 put_disk(pf->disk);
725 return -1;
726}
727
728/* The i/o request engine */
729
730static int pf_start(struct pf_unit *pf, int cmd, int b, int c)
731{
732 int i;
733 char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
734
735 for (i = 0; i < 4; i++) {
736 io_cmd[5 - i] = b & 0xff;
737 b = b >> 8;
738 }
739
740 io_cmd[8] = c & 0xff;
741 io_cmd[7] = (c >> 8) & 0xff;
742
743 i = pf_command(pf, io_cmd, c * 512, "start i/o");
744
745 mdelay(1);
746
747 return i;
748}
749
750static int pf_ready(void)
751{
752 return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));
753}
754
755static struct request_queue *pf_queue;
756
Tejun Heof06d9a22009-04-23 11:05:19 +0900757static void pf_end_request(int err)
Jens Axboe9564df12005-09-16 19:28:15 -0700758{
Tejun Heob12d4f82009-05-08 11:54:06 +0900759 if (pf_req && !__blk_end_request_cur(pf_req, err))
Jens Axboe9564df12005-09-16 19:28:15 -0700760 pf_req = NULL;
Jens Axboe9564df12005-09-16 19:28:15 -0700761}
762
Jens Axboe165125e2007-07-24 09:28:11 +0200763static void do_pf_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
765 if (pf_busy)
766 return;
767repeat:
Tejun Heob12d4f82009-05-08 11:54:06 +0900768 if (!pf_req) {
Tejun Heo9934c8c2009-05-08 11:54:16 +0900769 pf_req = blk_fetch_request(q);
Tejun Heob12d4f82009-05-08 11:54:06 +0900770 if (!pf_req)
771 return;
Tejun Heob12d4f82009-05-08 11:54:06 +0900772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 pf_current = pf_req->rq_disk->private_data;
Tejun Heo83096eb2009-05-07 22:24:39 +0900775 pf_block = blk_rq_pos(pf_req);
776 pf_run = blk_rq_sectors(pf_req);
777 pf_count = blk_rq_cur_sectors(pf_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
779 if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
Tejun Heof06d9a22009-04-23 11:05:19 +0900780 pf_end_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 goto repeat;
782 }
783
784 pf_cmd = rq_data_dir(pf_req);
785 pf_buf = pf_req->buffer;
786 pf_retries = 0;
787
788 pf_busy = 1;
789 if (pf_cmd == READ)
790 pi_do_claimed(pf_current->pi, do_pf_read);
791 else if (pf_cmd == WRITE)
792 pi_do_claimed(pf_current->pi, do_pf_write);
793 else {
794 pf_busy = 0;
Tejun Heof06d9a22009-04-23 11:05:19 +0900795 pf_end_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 goto repeat;
797 }
798}
799
800static int pf_next_buf(void)
801{
802 unsigned long saved_flags;
803
804 pf_count--;
805 pf_run--;
806 pf_buf += 512;
807 pf_block++;
808 if (!pf_run)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 return 1;
Ondrej Zarye62aa042007-11-14 16:59:24 -0800810 if (!pf_count) {
811 spin_lock_irqsave(&pf_spin_lock, saved_flags);
Tejun Heof06d9a22009-04-23 11:05:19 +0900812 pf_end_request(0);
Ondrej Zarye62aa042007-11-14 16:59:24 -0800813 spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
814 if (!pf_req)
815 return 1;
Tejun Heo83096eb2009-05-07 22:24:39 +0900816 pf_count = blk_rq_cur_sectors(pf_req);
Ondrej Zarye62aa042007-11-14 16:59:24 -0800817 pf_buf = pf_req->buffer;
818 }
819 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
Tejun Heof06d9a22009-04-23 11:05:19 +0900822static inline void next_request(int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
824 unsigned long saved_flags;
825
826 spin_lock_irqsave(&pf_spin_lock, saved_flags);
Tejun Heof06d9a22009-04-23 11:05:19 +0900827 pf_end_request(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 pf_busy = 0;
829 do_pf_request(pf_queue);
830 spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
831}
832
833/* detach from the calling context - in case the spinlock is held */
834static void do_pf_read(void)
835{
836 ps_set_intr(do_pf_read_start, NULL, 0, nice);
837}
838
839static void do_pf_read_start(void)
840{
841 pf_busy = 1;
842
843 if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) {
844 pi_disconnect(pf_current->pi);
845 if (pf_retries < PF_MAX_RETRIES) {
846 pf_retries++;
847 pi_do_claimed(pf_current->pi, do_pf_read_start);
848 return;
849 }
Tejun Heof06d9a22009-04-23 11:05:19 +0900850 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 return;
852 }
853 pf_mask = STAT_DRQ;
854 ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice);
855}
856
857static void do_pf_read_drq(void)
858{
859 while (1) {
860 if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
861 "read block", "completion") & STAT_ERR) {
862 pi_disconnect(pf_current->pi);
863 if (pf_retries < PF_MAX_RETRIES) {
864 pf_req_sense(pf_current, 0);
865 pf_retries++;
866 pi_do_claimed(pf_current->pi, do_pf_read_start);
867 return;
868 }
Tejun Heof06d9a22009-04-23 11:05:19 +0900869 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return;
871 }
872 pi_read_block(pf_current->pi, pf_buf, 512);
873 if (pf_next_buf())
874 break;
875 }
876 pi_disconnect(pf_current->pi);
Tejun Heof06d9a22009-04-23 11:05:19 +0900877 next_request(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878}
879
880static void do_pf_write(void)
881{
882 ps_set_intr(do_pf_write_start, NULL, 0, nice);
883}
884
885static void do_pf_write_start(void)
886{
887 pf_busy = 1;
888
889 if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) {
890 pi_disconnect(pf_current->pi);
891 if (pf_retries < PF_MAX_RETRIES) {
892 pf_retries++;
893 pi_do_claimed(pf_current->pi, do_pf_write_start);
894 return;
895 }
Tejun Heof06d9a22009-04-23 11:05:19 +0900896 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 return;
898 }
899
900 while (1) {
901 if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
902 "write block", "data wait") & STAT_ERR) {
903 pi_disconnect(pf_current->pi);
904 if (pf_retries < PF_MAX_RETRIES) {
905 pf_retries++;
906 pi_do_claimed(pf_current->pi, do_pf_write_start);
907 return;
908 }
Tejun Heof06d9a22009-04-23 11:05:19 +0900909 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 return;
911 }
912 pi_write_block(pf_current->pi, pf_buf, 512);
913 if (pf_next_buf())
914 break;
915 }
916 pf_mask = 0;
917 ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice);
918}
919
920static void do_pf_write_done(void)
921{
922 if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) {
923 pi_disconnect(pf_current->pi);
924 if (pf_retries < PF_MAX_RETRIES) {
925 pf_retries++;
926 pi_do_claimed(pf_current->pi, do_pf_write_start);
927 return;
928 }
Tejun Heof06d9a22009-04-23 11:05:19 +0900929 next_request(-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 return;
931 }
932 pi_disconnect(pf_current->pi);
Tejun Heof06d9a22009-04-23 11:05:19 +0900933 next_request(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
936static int __init pf_init(void)
937{ /* preliminary initialisation */
938 struct pf_unit *pf;
939 int unit;
940
941 if (disable)
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800942 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
944 pf_init_units();
945
946 if (pf_detect())
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800947 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 pf_busy = 0;
949
950 if (register_blkdev(major, name)) {
951 for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
952 put_disk(pf->disk);
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800953 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
955 pf_queue = blk_init_queue(do_pf_request, &pf_spin_lock);
956 if (!pf_queue) {
957 unregister_blkdev(major, name);
958 for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
959 put_disk(pf->disk);
Akinobu Mita8bca98c2006-12-06 20:36:43 -0800960 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 }
962
Martin K. Petersen8a783622010-02-26 00:20:39 -0500963 blk_queue_max_segments(pf_queue, cluster);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
965 for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
966 struct gendisk *disk = pf->disk;
967
968 if (!pf->present)
969 continue;
970 disk->private_data = pf;
971 disk->queue = pf_queue;
972 add_disk(disk);
973 }
974 return 0;
975}
976
977static void __exit pf_exit(void)
978{
979 struct pf_unit *pf;
980 int unit;
981 unregister_blkdev(major, name);
982 for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
983 if (!pf->present)
984 continue;
985 del_gendisk(pf->disk);
986 put_disk(pf->disk);
987 pi_release(pf->pi);
988 }
989 blk_cleanup_queue(pf_queue);
990}
991
992MODULE_LICENSE("GPL");
993module_init(pf_init)
994module_exit(pf_exit)