^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) Under the terms of the GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) This is the high-level driver for parallel port ATAPI disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) drives based on chips supported by the paride module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) By default, the driver will autoprobe for a single parallel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) port ATAPI disk drive, but if their individual parameters are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) specified, the driver can handle up to 4 drives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) The behaviour of the pf driver can be altered by setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) some parameters from the insmod command line. The following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) parameters are adjustable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) drive0 These four arguments can be arrays of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) drive1 1-7 integers as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) drive2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<lun>,<dly>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) Where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) <prt> is the base of the parallel port address for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) the corresponding drive. (required)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) <pro> is the protocol number for the adapter that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) supports this drive. These numbers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) logged by 'paride' when the protocol modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) are initialised. (0 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) <uni> for those adapters that support chained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) devices, this is the unit selector for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) chain of devices on the given port. It should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) be zero for devices that don't support chaining.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) (0 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) <mod> this can be -1 to choose the best mode, or one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) of the mode numbers supported by the adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) (-1 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) <slv> ATAPI CDroms can be jumpered to master or slave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) Set this to 0 to choose the master drive, 1 to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) choose the slave, -1 (the default) to choose the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) first drive found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) <lun> Some ATAPI devices support multiple LUNs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) One example is the ATAPI PD/CD drive from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) Matshita/Panasonic. This device has a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) CD drive on LUN 0 and a PD drive on LUN 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) By default, the driver will search for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) first LUN with a supported device. Set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) this parameter to force it to use a specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) LUN. (default -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) <dly> some parallel ports require the driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) go more slowly. -1 sets a default value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) should work with the chosen protocol. Otherwise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) set this to a small integer, the larger it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) the slower the port i/o. In some cases, setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) this to zero will speed up the device. (default -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) major You may use this parameter to override the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) default major number (47) that this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) will use. Be sure to change the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) name as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) name This parameter is a character string that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) contains the name the kernel will use for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) device (in /proc output, for instance).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (default "pf").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) cluster The driver will attempt to aggregate requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) for adjacent blocks into larger multi-block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) clusters. The maximum cluster size (in 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) byte sectors) is set with this parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) (default 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) verbose This parameter controls the amount of logging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) that the driver will do. Set it to 0 for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) normal operation, 1 to see autoprobe progress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) messages, or 2 to see additional debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) output. (default 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) nice This parameter controls the driver's use of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) idle CPU time, at the expense of some speed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) If this driver is built into the kernel, you can use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) following command line parameters, with the same values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) as the corresponding module parameters listed above:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pf.drive0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) pf.drive1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pf.drive2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) pf.drive3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pf.cluster
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) pf.nice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) In addition, you can use the parameter pf.disable to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) the driver entirely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) Fix for drives that don't clear STAT_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) until after next CDB delivered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) Small change in pf_completion to round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) up transfer size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 1.02 GRG 1998.06.16 Eliminated an Ugh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 1.04 GRG 1998.09.24 Added jumbo support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define PF_VERSION "1.04"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define PF_MAJOR 47
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define PF_NAME "pf"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define PF_UNITS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Here are things one can override from the insmod command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) Most are autoprobed by paride unless set here. Verbose is off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static bool verbose = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int major = PF_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static char *name = PF_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int cluster = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int nice = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int disable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int drive0[7] = { 0, 0, 0, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int drive1[7] = { 0, 0, 0, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static int drive2[7] = { 0, 0, 0, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int drive3[7] = { 0, 0, 0, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int (*drives[4])[7] = {&drive0, &drive1, &drive2, &drive3};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int pf_drive_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* end of parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #include <linux/hdreg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #include <linux/cdrom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #include <linux/blk-mq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #include <linux/blkpg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static DEFINE_MUTEX(pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static DEFINE_SPINLOCK(pf_spin_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) module_param(verbose, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) module_param(major, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) module_param(name, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) module_param(cluster, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) module_param(nice, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) module_param_array(drive0, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) module_param_array(drive1, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) module_param_array(drive2, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) module_param_array(drive3, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #include "paride.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #include "pseudo.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* constants for faking geometry numbers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define PF_FD_MAX 8192 /* use FD geometry under this size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define PF_FD_HDS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define PF_FD_SPT 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define PF_HD_HDS 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define PF_HD_SPT 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define PF_MAX_RETRIES 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define PF_TMO 800 /* interrupt timeout in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define PF_SPIN_DEL 50 /* spin delay in micro-seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define STAT_ERR 0x00001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define STAT_INDEX 0x00002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define STAT_ECC 0x00004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define STAT_DRQ 0x00008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define STAT_SEEK 0x00010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define STAT_WRERR 0x00020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define STAT_READY 0x00040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define STAT_BUSY 0x00080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define ATAPI_REQ_SENSE 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define ATAPI_LOCK 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define ATAPI_DOOR 0x1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define ATAPI_MODE_SENSE 0x5a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define ATAPI_CAPACITY 0x25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define ATAPI_IDENTIFY 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define ATAPI_READ_10 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define ATAPI_WRITE_10 0x2a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int pf_open(struct block_device *bdev, fmode_t mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) const struct blk_mq_queue_data *bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int pf_ioctl(struct block_device *bdev, fmode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static void pf_release(struct gendisk *disk, fmode_t mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int pf_detect(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void do_pf_read(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static void do_pf_read_start(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void do_pf_write(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void do_pf_write_start(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void do_pf_read_drq(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static void do_pf_write_done(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define PF_NM 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define PF_RO 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define PF_RW 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define PF_NAMELEN 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct pf_unit {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct pi_adapter pia; /* interface to paride layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct pi_adapter *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int removable; /* removable media device ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int media_status; /* media present ? WP ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int drive; /* drive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int lun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int access; /* count of active opens ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int present; /* device present ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) char name[PF_NAMELEN]; /* pf0, pf1, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct gendisk *disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct blk_mq_tag_set tag_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct list_head rq_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static struct pf_unit units[PF_UNITS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int pf_identify(struct pf_unit *pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static void pf_lock(struct pf_unit *pf, int func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void pf_eject(struct pf_unit *pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static unsigned int pf_check_events(struct gendisk *disk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) unsigned int clearing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static char pf_scratch[512]; /* scratch block buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* the variables below are used mainly in the I/O request engine, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) processes only one request at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static int pf_retries = 0; /* i/o error retry count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int pf_busy = 0; /* request being processed ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static struct request *pf_req; /* current request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int pf_block; /* address of next requested block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int pf_count; /* number of blocks still to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int pf_run; /* sectors in current cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int pf_cmd; /* current command READ/WRITE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static struct pf_unit *pf_current;/* unit of current request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static int pf_mask; /* stopper for pseudo-int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static char *pf_buf; /* buffer for request in progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void *par_drv; /* reference of parport driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* kernel glue structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static const struct block_device_operations pf_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .open = pf_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .release = pf_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .ioctl = pf_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .compat_ioctl = pf_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .getgeo = pf_getgeo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .check_events = pf_check_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static const struct blk_mq_ops pf_mq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .queue_rq = pf_queue_rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static void __init pf_init_units(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct pf_unit *pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pf_drive_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct gendisk *disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) disk = alloc_disk(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!disk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) disk->queue = blk_mq_init_sq_queue(&pf->tag_set, &pf_mq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 1, BLK_MQ_F_SHOULD_MERGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (IS_ERR(disk->queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) disk->queue = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) put_disk(disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) INIT_LIST_HEAD(&pf->rq_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) disk->queue->queuedata = pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) blk_queue_max_segments(disk->queue, cluster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pf->disk = disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pf->pi = &pf->pia;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pf->media_status = PF_NM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pf->drive = (*drives[unit])[D_SLV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pf->lun = (*drives[unit])[D_LUN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) snprintf(pf->name, PF_NAMELEN, "%s%d", name, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) disk->major = major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) disk->first_minor = unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) strcpy(disk->disk_name, pf->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) disk->fops = &pf_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) disk->events = DISK_EVENT_MEDIA_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!(*drives[unit])[D_PRT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) pf_drive_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int pf_open(struct block_device *bdev, fmode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct pf_unit *pf = bdev->bd_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) mutex_lock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) pf_identify(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (pf->media_status == PF_NM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pf->access++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (pf->removable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) pf_lock(pf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_unlock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct pf_unit *pf = bdev->bd_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) sector_t capacity = get_capacity(pf->disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (capacity < PF_FD_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) geo->heads = PF_FD_HDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) geo->sectors = PF_FD_SPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) geo->heads = PF_HD_HDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) geo->sectors = PF_HD_SPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct pf_unit *pf = bdev->bd_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (cmd != CDROMEJECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (pf->access != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) mutex_lock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pf_eject(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mutex_unlock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static void pf_release(struct gendisk *disk, fmode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct pf_unit *pf = disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mutex_lock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (pf->access <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) mutex_unlock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) pf->access--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!pf->access && pf->removable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) pf_lock(pf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) mutex_unlock(&pf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return DISK_EVENT_MEDIA_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static inline int status_reg(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return pi_read_regr(pf->pi, 1, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static inline int read_reg(struct pf_unit *pf, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return pi_read_regr(pf->pi, 0, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static inline void write_reg(struct pf_unit *pf, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) pi_write_regr(pf->pi, 0, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int pf_wait(struct pf_unit *pf, int go, int stop, char *fun, char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int j, r, e, s, p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) while ((((r = status_reg(pf)) & go) || (stop && (!(r & stop))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) && (j++ < PF_SPIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) udelay(PF_SPIN_DEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if ((r & (STAT_ERR & stop)) || (j > PF_SPIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) s = read_reg(pf, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) e = read_reg(pf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) p = read_reg(pf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (j > PF_SPIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) e |= 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) " loop=%d phase=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) pf->name, fun, msg, r, s, e, j, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return (e << 8) + s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int pf_command(struct pf_unit *pf, char *cmd, int dlen, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) pi_connect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) write_reg(pf, 6, 0xa0+0x10*pf->drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (pf_wait(pf, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) pi_disconnect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) write_reg(pf, 4, dlen % 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) write_reg(pf, 5, dlen / 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) write_reg(pf, 7, 0xa0); /* ATAPI packet command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (pf_wait(pf, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) pi_disconnect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (read_reg(pf, 2) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) printk("%s: %s: command phase error\n", pf->name, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) pi_disconnect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pi_write_block(pf->pi, cmd, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int pf_completion(struct pf_unit *pf, char *buf, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int r, s, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) r = pf_wait(pf, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) fun, "completion");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if ((read_reg(pf, 2) & 2) && (read_reg(pf, 7) & STAT_DRQ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) n = (((read_reg(pf, 4) + 256 * read_reg(pf, 5)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 3) & 0xfffc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pi_read_block(pf->pi, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) s = pf_wait(pf, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) pi_disconnect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return (r ? r : s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static void pf_req_sense(struct pf_unit *pf, int quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) char rs_cmd[12] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) { ATAPI_REQ_SENSE, pf->lun << 5, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) char buf[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) r = pf_command(pf, rs_cmd, 16, "Request sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) pf_completion(pf, buf, "Request sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if ((!r) && (!quiet))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) pf->name, buf[2] & 0xf, buf[12], buf[13]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) r = pf_command(pf, cmd, dlen, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) r = pf_completion(pf, buf, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pf_req_sense(pf, !fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static void pf_lock(struct pf_unit *pf, int func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static void pf_eject(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) pf_lock(pf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) #define PF_RESET_TMO 30 /* in tenths of a second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static void pf_sleep(int cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) schedule_timeout_interruptible(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* the ATAPI standard actually specifies the contents of all 7 registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) after a reset, but the specification is ambiguous concerning the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) two bytes, and different drives interpret the standard differently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static int pf_reset(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int i, k, flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int expect[5] = { 1, 1, 1, 0x14, 0xeb };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) pi_connect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) write_reg(pf, 6, 0xa0+0x10*pf->drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) write_reg(pf, 7, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pf_sleep(20 * HZ / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) pf_sleep(HZ / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) flg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for (i = 0; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) flg &= (read_reg(pf, i + 1) == expect[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) printk("%s: Reset (%d) signature = ", pf->name, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) for (i = 0; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) printk("%3x", read_reg(pf, i + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (!flg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) printk(" (incorrect)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) pi_disconnect(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return flg - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static void pf_mode_sense(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) char ms_cmd[12] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) char buf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pf->media_status = PF_RW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (buf[3] & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) pf->media_status = PF_RO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static void xs(char *buf, char *targ, int offs, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) int j, k, l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) for (k = 0; k < len; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) l = targ[j++] = buf[k + offs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (l == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) j--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) targ[j] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int xl(char *buf, int offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int v, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) for (k = 0; k < 4; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) v = v * 256 + (buf[k + offs] & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static void pf_get_capacity(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) char rc_cmd[12] = { ATAPI_CAPACITY, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) char buf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int bs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) pf->media_status = PF_NM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) set_capacity(pf->disk, xl(buf, 0) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) bs = xl(buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (bs != 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) set_capacity(pf->disk, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) printk("%s: Drive %d, LUN %d,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) " unsupported block size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pf->name, pf->drive, pf->lun, bs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int pf_identify(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int dt, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) char *ms[2] = { "master", "slave" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) char mf[10], id[18];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) char id_cmd[12] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) char buf[36];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) s = pf_atapi(pf, id_cmd, 36, buf, "identify");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dt = buf[0] & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if ((dt != 0) && (dt != 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) printk("%s: Drive %d, LUN %d, unsupported type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) pf->name, pf->drive, pf->lun, dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) xs(buf, mf, 8, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) xs(buf, id, 16, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) pf->removable = (buf[1] & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) pf_mode_sense(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) pf_mode_sense(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) pf_mode_sense(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) pf_get_capacity(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) printk("%s: %s %s, %s LUN %d, type %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) pf->name, mf, id, ms[pf->drive], pf->lun, dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (pf->removable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) printk(", removable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (pf->media_status == PF_NM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) printk(", no media\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (pf->media_status == PF_RO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) printk(", RO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) printk(", %llu blocks\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) (unsigned long long)get_capacity(pf->disk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* returns 0, with id set if drive is detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) -1, if drive detection failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int pf_probe(struct pf_unit *pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (pf->drive == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) for (pf->drive = 0; pf->drive <= 1; pf->drive++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!pf_reset(pf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (pf->lun != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return pf_identify(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) for (pf->lun = 0; pf->lun < 8; pf->lun++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (!pf_identify(pf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (pf_reset(pf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (pf->lun != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return pf_identify(pf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) for (pf->lun = 0; pf->lun < 8; pf->lun++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!pf_identify(pf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static int pf_detect(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct pf_unit *pf = units;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int k, unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) name, name, PF_VERSION, major, cluster, nice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) par_drv = pi_register_driver(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (!par_drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) pr_err("failed to register %s driver\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (pf_drive_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (pi_init(pf->pi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) verbose, pf->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (!pf_probe(pf) && pf->disk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) pf->present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) pi_release(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) for (unit = 0; unit < PF_UNITS; unit++, pf++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int *conf = *drives[unit];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (!conf[D_PRT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) conf[D_UNI], conf[D_PRO], conf[D_DLY],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) pf_scratch, PI_PF, verbose, pf->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (pf->disk && !pf_probe(pf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) pf->present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pi_release(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) printk("%s: No ATAPI disk detected\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (!pf->disk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) blk_cleanup_queue(pf->disk->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) pf->disk->queue = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) blk_mq_free_tag_set(&pf->tag_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) put_disk(pf->disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) pi_unregister_driver(par_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* The i/o request engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static int pf_start(struct pf_unit *pf, int cmd, int b, int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) io_cmd[5 - i] = b & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) b = b >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) io_cmd[8] = c & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) io_cmd[7] = (c >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) i = pf_command(pf, io_cmd, c * 512, "start i/o");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int pf_ready(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static int pf_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static int set_next_request(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct pf_unit *pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int old_pos = pf_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) pf = &units[pf_queue];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (++pf_queue == PF_UNITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pf_queue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (pf->present && !list_empty(&pf->rq_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) pf_req = list_first_entry(&pf->rq_list, struct request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) queuelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) list_del_init(&pf_req->queuelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) blk_mq_start_request(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) } while (pf_queue != old_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return pf_req != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static void pf_end_request(blk_status_t err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (!pf_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!blk_update_request(pf_req, err, blk_rq_cur_bytes(pf_req))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) __blk_mq_end_request(pf_req, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) pf_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static void pf_request(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (pf_busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) repeat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!pf_req && !set_next_request())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) pf_current = pf_req->rq_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) pf_block = blk_rq_pos(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) pf_run = blk_rq_sectors(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) pf_count = blk_rq_cur_sectors(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) pf_end_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) goto repeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) pf_cmd = rq_data_dir(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pf_buf = bio_data(pf_req->bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pf_retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pf_busy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (pf_cmd == READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) pi_do_claimed(pf_current->pi, do_pf_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) else if (pf_cmd == WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) pi_do_claimed(pf_current->pi, do_pf_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) pf_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) pf_end_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto repeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) const struct blk_mq_queue_data *bd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct pf_unit *pf = hctx->queue->queuedata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) spin_lock_irq(&pf_spin_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) list_add_tail(&bd->rq->queuelist, &pf->rq_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pf_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) spin_unlock_irq(&pf_spin_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return BLK_STS_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static int pf_next_buf(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) unsigned long saved_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) pf_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) pf_run--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) pf_buf += 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) pf_block++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (!pf_run)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (!pf_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) spin_lock_irqsave(&pf_spin_lock, saved_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) pf_end_request(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (!pf_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) pf_count = blk_rq_cur_sectors(pf_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) pf_buf = bio_data(pf_req->bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static inline void next_request(blk_status_t err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) unsigned long saved_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) spin_lock_irqsave(&pf_spin_lock, saved_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) pf_end_request(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) pf_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) pf_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* detach from the calling context - in case the spinlock is held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static void do_pf_read(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ps_set_intr(do_pf_read_start, NULL, 0, nice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static void do_pf_read_start(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) pf_busy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (pf_retries < PF_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) pf_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) pi_do_claimed(pf_current->pi, do_pf_read_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) next_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) pf_mask = STAT_DRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static void do_pf_read_drq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) "read block", "completion") & STAT_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (pf_retries < PF_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) pf_req_sense(pf_current, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pf_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) pi_do_claimed(pf_current->pi, do_pf_read_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) next_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) pi_read_block(pf_current->pi, pf_buf, 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (pf_next_buf())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) next_request(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static void do_pf_write(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) ps_set_intr(do_pf_write_start, NULL, 0, nice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) static void do_pf_write_start(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pf_busy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (pf_retries < PF_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pf_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) pi_do_claimed(pf_current->pi, do_pf_write_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) next_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) "write block", "data wait") & STAT_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (pf_retries < PF_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) pf_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) pi_do_claimed(pf_current->pi, do_pf_write_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) next_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pi_write_block(pf_current->pi, pf_buf, 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (pf_next_buf())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) pf_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) static void do_pf_write_done(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (pf_retries < PF_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) pf_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) pi_do_claimed(pf_current->pi, do_pf_write_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) next_request(BLK_STS_IOERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) pi_disconnect(pf_current->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) next_request(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static int __init pf_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) { /* preliminary initialisation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct pf_unit *pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) pf_init_units();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (pf_detect())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) pf_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (register_blkdev(major, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (!pf->disk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) blk_cleanup_queue(pf->disk->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) blk_mq_free_tag_set(&pf->tag_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) put_disk(pf->disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) struct gendisk *disk = pf->disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (!pf->present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) disk->private_data = pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) add_disk(disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static void __exit pf_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct pf_unit *pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) unregister_blkdev(major, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!pf->disk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (pf->present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) del_gendisk(pf->disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) blk_cleanup_queue(pf->disk->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) blk_mq_free_tag_set(&pf->tag_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) put_disk(pf->disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (pf->present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) pi_release(pf->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) module_init(pf_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) module_exit(pf_exit)