Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)