^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) pt.c (c) 1998 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 tape
^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) The driver implements both rewinding and non-rewinding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) devices, filemarks, and the rewind ioctl. It allocates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) a small internal "bounce buffer" for each open device, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) otherwise expects buffering and blocking to be done at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) user level. As with most block-structured tapes, short
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) writes are padded to full tape blocks, so reading back a file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) may return more data than was actually written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) By default, the driver will autoprobe for a single parallel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) port ATAPI tape drive, but if their individual parameters are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) specified, the driver can handle up to 4 drives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) The rewinding devices are named /dev/pt0, /dev/pt1, ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) The behaviour of the pt driver can be altered by setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) some parameters from the insmod command line. The following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) parameters are adjustable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) drive0 These four arguments can be arrays of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) drive1 1-6 integers as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) drive2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) Where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) <prt> is the base of the parallel port address for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) the corresponding drive. (required)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) <pro> is the protocol number for the adapter that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) supports this drive. These numbers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) logged by 'paride' when the protocol modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) are initialised. (0 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) <uni> for those adapters that support chained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) devices, this is the unit selector for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) chain of devices on the given port. It should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) be zero for devices that don't support chaining.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) (0 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) <mod> this can be -1 to choose the best mode, or one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) of the mode numbers supported by the adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) (-1 if not given)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) <slv> ATAPI devices can be jumpered to master or slave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) Set this to 0 to choose the master drive, 1 to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) choose the slave, -1 (the default) to choose the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) first drive found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) <dly> some parallel ports require the driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) go more slowly. -1 sets a default value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) should work with the chosen protocol. Otherwise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) set this to a small integer, the larger it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) the slower the port i/o. In some cases, setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) this to zero will speed up the device. (default -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) major You may use this parameter to override the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) default major number (96) that this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) will use. Be sure to change the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) name as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) name This parameter is a character string that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) contains the name the kernel will use for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) device (in /proc output, for instance).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) (default "pt").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) verbose This parameter controls the amount of logging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) that the driver will do. Set it to 0 for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) normal operation, 1 to see autoprobe progress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) messages, or 2 to see additional debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) output. (default 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) If this driver is built into the kernel, you can use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) the following command line parameters, with the same values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) as the corresponding module parameters listed above:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pt.drive0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pt.drive1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pt.drive2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pt.drive3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) In addition, you can use the parameter pt.disable to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) the driver entirely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 1.01 GRG 1998.05.06 Round up transfer size, fix ready_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) loosed interpretation of ATAPI standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) for clearing error status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) Eliminate sti();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 1.02 GRG 1998.06.16 Eliminate an Ugh.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) extra debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PT_VERSION "1.04"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define PT_MAJOR 96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define PT_NAME "pt"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PT_UNITS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Here are things one can override from the insmod command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) Most are autoprobed by paride unless set here. Verbose is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int verbose = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int major = PT_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static char *name = PT_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int disable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define D_PRT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define D_PRO 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define D_UNI 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define D_MOD 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define D_SLV 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define D_DLY 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define DU (*drives[unit])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* end of parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #include <linux/mtio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) module_param(verbose, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) module_param(major, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) module_param(name, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) module_param_array(drive0, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) module_param_array(drive1, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) module_param_array(drive2, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) module_param_array(drive3, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #include "paride.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define PT_MAX_RETRIES 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define PT_TMO 3000 /* interrupt timeout in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define PT_RESET_TMO 30 /* 30 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define PT_READY_TMO 60 /* 60 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define PT_REWIND_TMO 1200 /* 20 minutes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define STAT_ERR 0x00001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define STAT_INDEX 0x00002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define STAT_ECC 0x00004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define STAT_DRQ 0x00008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define STAT_SEEK 0x00010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define STAT_WRERR 0x00020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define STAT_READY 0x00040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define STAT_BUSY 0x00080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define STAT_SENSE 0x1f000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define ATAPI_TEST_READY 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define ATAPI_REWIND 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define ATAPI_REQ_SENSE 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define ATAPI_READ_6 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define ATAPI_WRITE_6 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define ATAPI_WFM 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define ATAPI_IDENTIFY 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define ATAPI_MODE_SENSE 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define ATAPI_LOG_SENSE 0x4d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static DEFINE_MUTEX(pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int pt_open(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int pt_release(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static ssize_t pt_read(struct file *filp, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) size_t count, loff_t * ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static ssize_t pt_write(struct file *filp, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) size_t count, loff_t * ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int pt_detect(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* bits in tape->flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define PT_MEDIA 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define PT_WRITE_OK 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define PT_REWIND 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #define PT_WRITING 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define PT_READING 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define PT_EOF 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define PT_NAMELEN 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define PT_BUFSIZE 16384
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct pt_unit {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct pi_adapter pia; /* interface to paride layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct pi_adapter *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int flags; /* various state flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int last_sense; /* result of last request sense */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int drive; /* drive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) atomic_t available; /* 1 if access is available 0 otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int bs; /* block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int capacity; /* Size of tape in KB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int present; /* device present ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) char *bufptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) char name[PT_NAMELEN]; /* pf0, pf1, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static int pt_identify(struct pt_unit *tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct pt_unit pt[PT_UNITS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static char pt_scratch[512]; /* scratch block buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static void *par_drv; /* reference of parport driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* kernel glue structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static const struct file_operations pt_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .read = pt_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .write = pt_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .unlocked_ioctl = pt_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .open = pt_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .release = pt_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* sysfs class support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static struct class *pt_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static inline int status_reg(struct pi_adapter *pi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return pi_read_regr(pi, 1, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static inline int read_reg(struct pi_adapter *pi, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return pi_read_regr(pi, 0, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static inline void write_reg(struct pi_adapter *pi, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pi_write_regr(pi, 0, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static inline u8 DRIVE(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return 0xa0+0x10*tape->drive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int j, r, e, s, p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) && (j++ < PT_SPIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) udelay(PT_SPIN_DEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if ((r & (STAT_ERR & stop)) || (j > PT_SPIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) s = read_reg(pi, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) e = read_reg(pi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) p = read_reg(pi, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (j > PT_SPIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) e |= 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) " loop=%d phase=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) tape->name, fun, msg, r, s, e, j, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return (e << 8) + s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pi_connect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) write_reg(pi, 6, DRIVE(tape));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -1;
^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) write_reg(pi, 4, dlen % 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) write_reg(pi, 5, dlen / 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) write_reg(pi, 7, 0xa0); /* ATAPI packet command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (read_reg(pi, 2) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) printk("%s: %s: command phase error\n", tape->name, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pi_write_block(pi, cmd, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^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 pt_completion(struct pt_unit *tape, char *buf, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int r, s, n, p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) fun, "completion");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (read_reg(pi, 7) & STAT_DRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 3) & 0xfffc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) p = read_reg(pi, 2) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (p == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pi_write_block(pi, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (p == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) pi_read_block(pi, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return (r ? r : s);
^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 void pt_req_sense(struct pt_unit *tape, int quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) char buf[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) r = pt_command(tape, rs_cmd, 16, "Request sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pt_completion(tape, buf, "Request sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) tape->last_sense = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) tape->name, buf[2] & 0xf, buf[12], buf[13]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) | ((buf[13] & 0xff) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) r = pt_command(tape, cmd, dlen, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) r = pt_completion(tape, buf, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pt_req_sense(tape, !fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void pt_sleep(int cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) schedule_timeout_interruptible(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int k, e, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) s = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) while (k < tmo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) pt_sleep(pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) pi_connect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) write_reg(pi, 6, DRIVE(tape));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) s = read_reg(pi, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) e = read_reg(pi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (s & (STAT_ERR | STAT_SEEK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if ((k >= tmo) || (s & STAT_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (k >= tmo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) printk("%s: %s DSC timeout\n", tape->name, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (pt_command(tape, cmd, 0, fun)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pi_disconnect(tape->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pt_poll_dsc(tape, HZ, tmo, fun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static void pt_rewind(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void pt_write_fm(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) #define DBMSG(msg) ((verbose>1)?(msg):NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int pt_reset(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int i, k, flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int expect[5] = { 1, 1, 1, 0x14, 0xeb };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pi_connect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) write_reg(pi, 6, DRIVE(tape));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) write_reg(pi, 7, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) pt_sleep(20 * HZ / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) pt_sleep(HZ / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) flg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) for (i = 0; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) flg &= (read_reg(pi, i + 1) == expect[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) printk("%s: Reset (%d) signature = ", tape->name, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) for (i = 0; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) printk("%3x", read_reg(pi, i + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (!flg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) printk(" (incorrect)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return flg - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int pt_ready_wait(struct pt_unit *tape, int tmo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int k, p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) while (k < tmo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tape->last_sense = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) p = tape->last_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) pt_sleep(HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return 0x000020; /* timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void xs(char *buf, char *targ, int offs, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int j, k, l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) for (k = 0; k < len; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) l = targ[j++] = buf[k + offs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (l == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) j--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) targ[j] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int xn(char *buf, int offs, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) int v, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) for (k = 0; k < size; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) v = v * 256 + (buf[k + offs] & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int pt_identify(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int dt, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) char *ms[2] = { "master", "slave" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) char mf[10], id[18];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) char ms_cmd[12] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) char ls_cmd[12] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) char buf[36];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) s = pt_atapi(tape, id_cmd, 36, buf, "identify");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dt = buf[0] & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (dt != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) printk("%s: Drive %d, unsupported type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) tape->name, tape->drive, dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) xs(buf, mf, 8, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) xs(buf, id, 16, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) tape->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) tape->capacity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) tape->bs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!pt_ready_wait(tape, PT_READY_TMO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) tape->flags |= PT_MEDIA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!(buf[2] & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) tape->flags |= PT_WRITE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) tape->bs = xn(buf, 10, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) tape->capacity = xn(buf, 24, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (!(tape->flags & PT_MEDIA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) printk(", no media\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!(tape->flags & PT_WRITE_OK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) printk(", RO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * returns 0, with id set if drive is detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * -1, if drive detection failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int pt_probe(struct pt_unit *tape)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (tape->drive == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) for (tape->drive = 0; tape->drive <= 1; tape->drive++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (!pt_reset(tape))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return pt_identify(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!pt_reset(tape))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return pt_identify(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static int pt_detect(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct pt_unit *tape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) int specified = 0, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) par_drv = pi_register_driver(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!par_drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) pr_err("failed to register %s driver\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) specified = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) for (unit = 0; unit < PT_UNITS; unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct pt_unit *tape = &pt[unit];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) tape->pi = &tape->pia;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) atomic_set(&tape->available, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) tape->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) tape->last_sense = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) tape->present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) tape->bufptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) tape->drive = DU[D_SLV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (!DU[D_PRT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) specified++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) verbose, tape->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (!pt_probe(tape)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) tape->present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pi_release(tape->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (specified == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) tape = pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) PI_PT, verbose, tape->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!pt_probe(tape)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) tape->present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) pi_release(tape->pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pi_unregister_driver(par_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) printk("%s: No ATAPI tape drive detected\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static int pt_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) int unit = iminor(inode) & 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct pt_unit *tape = pt + unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) mutex_lock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (unit >= PT_UNITS || (!tape->present)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mutex_unlock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (!atomic_dec_and_test(&tape->available))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) pt_identify(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (!(tape->flags & PT_MEDIA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & FMODE_WRITE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!(iminor(inode) & 128))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) tape->flags |= PT_REWIND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (tape->bufptr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) printk("%s: buffer allocation failed\n", tape->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) file->private_data = tape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) mutex_unlock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) atomic_inc(&tape->available);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) mutex_unlock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct pt_unit *tape = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) struct mtop __user *p = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct mtop mtop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case MTIOCTOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (copy_from_user(&mtop, p, sizeof(struct mtop)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) switch (mtop.mt_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case MTREW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) mutex_lock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) pt_rewind(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) mutex_unlock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case MTWEOF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) mutex_lock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) pt_write_fm(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) mutex_unlock(&pt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* FIXME: rate limit ?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) mtop.mt_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pt_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct pt_unit *tape = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (atomic_read(&tape->available) > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (tape->flags & PT_WRITING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) pt_write_fm(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (tape->flags & PT_REWIND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) pt_rewind(tape);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) kfree(tape->bufptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) tape->bufptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) atomic_inc(&tape->available);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct pt_unit *tape = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int k, n, r, p, s, t, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!(tape->flags & (PT_READING | PT_WRITING))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) tape->flags |= PT_READING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) } else if (tape->flags & PT_WRITING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (tape->flags & PT_EOF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) t = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) n = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (n > 32768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) n = 32768; /* max per command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) b = (n - 1 + tape->bs) / tape->bs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) n = b * tape->bs; /* rounded up to even block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) rd_cmd[4] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) r = pt_command(tape, rd_cmd, n, "read");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) r = pt_wait(tape, STAT_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) STAT_DRQ | STAT_ERR | STAT_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) DBMSG("read DRQ"), "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (r & STAT_SENSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) tape->flags |= PT_EOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) s = read_reg(pi, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (!(s & STAT_DRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) p = (read_reg(pi, 2) & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (p != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) printk("%s: Phase error on read: %d\n", tape->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) while (n > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) k = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (k > PT_BUFSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) k = PT_BUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) pi_read_block(pi, tape->bufptr, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) n -= k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) b = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (b > count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) b = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (copy_to_user(buf + t, tape->bufptr, b)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) t += b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) count -= b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (tape->flags & PT_EOF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct pt_unit *tape = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct pi_adapter *pi = tape->pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int k, n, r, p, s, t, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (!(tape->flags & PT_WRITE_OK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (!(tape->flags & (PT_READING | PT_WRITING))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) tape->flags |= PT_WRITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (pt_atapi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) (tape, wr_cmd, 0, NULL, "start buffer-available mode"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) } else if (tape->flags & PT_READING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (tape->flags & PT_EOF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) t = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) n = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (n > 32768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) n = 32768; /* max per command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) b = (n - 1 + tape->bs) / tape->bs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) n = b * tape->bs; /* rounded up to even block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) wr_cmd[4] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) r = pt_command(tape, wr_cmd, n, "write");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (r) { /* error delivering command only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return -EIO;
^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) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) r = pt_wait(tape, STAT_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) STAT_DRQ | STAT_ERR | STAT_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) DBMSG("write DRQ"), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (r & STAT_SENSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) pt_req_sense(tape, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) tape->flags |= PT_EOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) s = read_reg(pi, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (!(s & STAT_DRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) p = (read_reg(pi, 2) & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (p != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) printk("%s: Phase error on write: %d \n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) tape->name, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) while (n > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) k = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (k > PT_BUFSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) k = PT_BUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) b = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (b > count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) b = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (copy_from_user(tape->bufptr, buf + t, b)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) pi_write_block(pi, tape->bufptr, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) t += b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) count -= b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) n -= k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) pi_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (tape->flags & PT_EOF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static int __init pt_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (disable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (pt_detect()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) err = register_chrdev(major, name, &pt_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) printk("pt_init: unable to get major number %d\n", major);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) for (unit = 0; unit < PT_UNITS; unit++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (pt[unit].present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) pi_release(pt[unit].pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) major = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) pt_class = class_create(THIS_MODULE, "pt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (IS_ERR(pt_class)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) err = PTR_ERR(pt_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto out_chrdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) for (unit = 0; unit < PT_UNITS; unit++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (pt[unit].present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) device_create(pt_class, NULL, MKDEV(major, unit), NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) "pt%d", unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) device_create(pt_class, NULL, MKDEV(major, unit + 128),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) NULL, "pt%dn", unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) out_chrdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) unregister_chrdev(major, "pt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static void __exit pt_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) int unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) for (unit = 0; unit < PT_UNITS; unit++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (pt[unit].present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) device_destroy(pt_class, MKDEV(major, unit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) device_destroy(pt_class, MKDEV(major, unit + 128));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) class_destroy(pt_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unregister_chrdev(major, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) for (unit = 0; unit < PT_UNITS; unit++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (pt[unit].present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) pi_release(pt[unit].pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) module_init(pt_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) module_exit(pt_exit)