/*
pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
Under the terms of the GNU General Public License.
This is the high-level driver for parallel port ATAPI disk
drives based on chips supported by the paride module.
By default, the driver will autoprobe for a single parallel
port ATAPI disk drive, but if their individual parameters are
specified, the driver can handle up to 4 drives.
The behaviour of the pf driver can be altered by setting
some parameters from the insmod command line. The following
parameters are adjustable:
drive0 These four arguments can be arrays of
drive1 1-7 integers as follows:
drive2
drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<lun>,<dly>
Where,
<prt> is the base of the parallel port address for
the corresponding drive. (required)
<pro> is the protocol number for the adapter that
supports this drive. These numbers are
logged by 'paride' when the protocol modules
are initialised. (0 if not given)
<uni> for those adapters that support chained
devices, this is the unit selector for the
chain of devices on the given port. It should
be zero for devices that don't support chaining.
(0 if not given)
<mod> this can be -1 to choose the best mode, or one
of the mode numbers supported by the adapter.
(-1 if not given)
<slv> ATAPI CDroms can be jumpered to master or slave.
Set this to 0 to choose the master drive, 1 to
choose the slave, -1 (the default) to choose the
first drive found.
<lun> Some ATAPI devices support multiple LUNs.
One example is the ATAPI PD/CD drive from
Matshita/Panasonic. This device has a
CD drive on LUN 0 and a PD drive on LUN 1.
By default, the driver will search for the
first LUN with a supported device. Set
this parameter to force it to use a specific
LUN. (default -1)
<dly> some parallel ports require the driver to
go more slowly. -1 sets a default value that
should work with the chosen protocol. Otherwise,
set this to a small integer, the larger it is
the slower the port i/o. In some cases, setting
this to zero will speed up the device. (default -1)
major You may use this parameter to override the
default major number (47) that this driver
will use. Be sure to change the device
name as well.
name This parameter is a character string that
contains the name the kernel will use for this
device (in /proc output, for instance).
(default "pf").
cluster The driver will attempt to aggregate requests
for adjacent blocks into larger multi-block
clusters. The maximum cluster size (in 512
byte sectors) is set with this parameter.
(default 64)
verbose This parameter controls the amount of logging
that the driver will do. Set it to 0 for
normal operation, 1 to see autoprobe progress
messages, or 2 to see additional debugging
output. (default 0)
nice This parameter controls the driver's use of
idle CPU time, at the expense of some speed.
If this driver is built into the kernel, you can use the
following command line parameters, with the same values
as the corresponding module parameters listed above:
pf.drive0
pf.drive1
pf.drive2
pf.drive3
pf.cluster
pf.nice
In addition, you can use the parameter pf.disable to disable
the driver entirely.
*/
/* Changes:
1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti().
Fix for drives that don't clear STAT_ERR
until after next CDB delivered.
Small change in pf_completion to round
up transfer size.
1.02 GRG 1998.06.16 Eliminated an Ugh
1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging
1.04 GRG 1998.09.24 Added jumbo support
*/
#define PF_VERSION "1.04"
#define PF_MAJOR 47
#define PF_NAME "pf"
#define PF_UNITS 4
#include <linux/types.h>
/* Here are things one can override from the insmod command.
Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
static bool verbose = 0;
static int major = PF_MAJOR;
static char *name = PF_NAME;
static int cluster = 64;
static int nice = 0;
static int disable = 0;
static int drive0[7] = { 0, 0, 0, -1, -1, -1, -1 };
static int drive1[7] = { 0, 0, 0, -1, -1, -1, -1 };
static int drive2[7] = { 0, 0, 0, -1, -1, -1, -1 };
static int drive3[7] = { 0, 0, 0, -1, -1, -1, -1 };
static int (*drives[4])[7] = {&drive0, &drive1, &drive2, &drive3};
static int pf_drive_count;
enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
/* end of parameters */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h>
#include <linux/spinlock.h>
#include <linux/blk-mq.h>
#include <linux/blkpg.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
static DEFINE_MUTEX(pf_mutex);
static DEFINE_SPINLOCK(pf_spin_lock);
module_param(verbose, bool, 0644);
module_param(major, int, 0);
module_param(name, charp, 0);
module_param(cluster, int, 0);
module_param(nice, int, 0);
module_param_array(drive0, int, NULL, 0);
module_param_array(drive1, int, NULL, 0);
module_param_array(drive2, int, NULL, 0);
module_param_array(drive3, int, NULL, 0);
#include "paride.h"
#include "pseudo.h"
/* constants for faking geometry numbers */
#define PF_FD_MAX 8192 /* use FD geometry under this size */
#define PF_FD_HDS 2
#define PF_FD_SPT 18
#define PF_HD_HDS 64
#define PF_HD_SPT 32
#define PF_MAX_RETRIES 5
#define PF_TMO 800 /* interrupt timeout in jiffies */
#define PF_SPIN_DEL 50 /* spin delay in micro-seconds */
#define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)