xref: /OK3568_Linux_fs/kernel/drivers/block/paride/pg.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun 	pg.c    (c) 1998  Grant R. Guenther <grant@torque.net>
3*4882a593Smuzhiyun 			  Under the terms of the GNU General Public License.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun 	The pg driver provides a simple character device interface for
6*4882a593Smuzhiyun 	sending ATAPI commands to a device.  With the exception of the
7*4882a593Smuzhiyun 	ATAPI reset operation, all operations are performed by a pair
8*4882a593Smuzhiyun 	of read and write operations to the appropriate /dev/pgN device.
9*4882a593Smuzhiyun 	A write operation delivers a command and any outbound data in
10*4882a593Smuzhiyun 	a single buffer.  Normally, the write will succeed unless the
11*4882a593Smuzhiyun 	device is offline or malfunctioning, or there is already another
12*4882a593Smuzhiyun 	command pending.  If the write succeeds, it should be followed
13*4882a593Smuzhiyun 	immediately by a read operation, to obtain any returned data and
14*4882a593Smuzhiyun 	status information.  A read will fail if there is no operation
15*4882a593Smuzhiyun 	in progress.
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun 	As a special case, the device can be reset with a write operation,
18*4882a593Smuzhiyun 	and in this case, no following read is expected, or permitted.
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	There are no ioctl() operations.  Any single operation
21*4882a593Smuzhiyun 	may transfer at most PG_MAX_DATA bytes.  Note that the driver must
22*4882a593Smuzhiyun 	copy the data through an internal buffer.  In keeping with all
23*4882a593Smuzhiyun 	current ATAPI devices, command packets are assumed to be exactly
24*4882a593Smuzhiyun 	12 bytes in length.
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 	To permit future changes to this interface, the headers in the
27*4882a593Smuzhiyun 	read and write buffers contain a single character "magic" flag.
28*4882a593Smuzhiyun 	Currently this flag must be the character "P".
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	By default, the driver will autoprobe for a single parallel
31*4882a593Smuzhiyun 	port ATAPI device, but if their individual parameters are
32*4882a593Smuzhiyun 	specified, the driver can handle up to 4 devices.
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	To use this device, you must have the following device
35*4882a593Smuzhiyun 	special files defined:
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 		/dev/pg0 c 97 0
38*4882a593Smuzhiyun 		/dev/pg1 c 97 1
39*4882a593Smuzhiyun 		/dev/pg2 c 97 2
40*4882a593Smuzhiyun 		/dev/pg3 c 97 3
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	(You'll need to change the 97 to something else if you use
43*4882a593Smuzhiyun 	the 'major' parameter to install the driver on a different
44*4882a593Smuzhiyun 	major number.)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	The behaviour of the pg driver can be altered by setting
47*4882a593Smuzhiyun 	some parameters from the insmod command line.  The following
48*4882a593Smuzhiyun 	parameters are adjustable:
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	    drive0      These four arguments can be arrays of
51*4882a593Smuzhiyun 	    drive1      1-6 integers as follows:
52*4882a593Smuzhiyun 	    drive2
53*4882a593Smuzhiyun 	    drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 			Where,
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 		<prt>   is the base of the parallel port address for
58*4882a593Smuzhiyun 			the corresponding drive.  (required)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 		<pro>   is the protocol number for the adapter that
61*4882a593Smuzhiyun 			supports this drive.  These numbers are
62*4882a593Smuzhiyun 			logged by 'paride' when the protocol modules
63*4882a593Smuzhiyun 			are initialised.  (0 if not given)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 		<uni>   for those adapters that support chained
66*4882a593Smuzhiyun 			devices, this is the unit selector for the
67*4882a593Smuzhiyun 			chain of devices on the given port.  It should
68*4882a593Smuzhiyun 			be zero for devices that don't support chaining.
69*4882a593Smuzhiyun 			(0 if not given)
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		<mod>   this can be -1 to choose the best mode, or one
72*4882a593Smuzhiyun 			of the mode numbers supported by the adapter.
73*4882a593Smuzhiyun 			(-1 if not given)
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 		<slv>   ATAPI devices can be jumpered to master or slave.
76*4882a593Smuzhiyun 			Set this to 0 to choose the master drive, 1 to
77*4882a593Smuzhiyun 			choose the slave, -1 (the default) to choose the
78*4882a593Smuzhiyun 			first drive found.
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 		<dly>   some parallel ports require the driver to
81*4882a593Smuzhiyun 			go more slowly.  -1 sets a default value that
82*4882a593Smuzhiyun 			should work with the chosen protocol.  Otherwise,
83*4882a593Smuzhiyun 			set this to a small integer, the larger it is
84*4882a593Smuzhiyun 			the slower the port i/o.  In some cases, setting
85*4882a593Smuzhiyun 			this to zero will speed up the device. (default -1)
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	    major	You may use this parameter to override the
88*4882a593Smuzhiyun 			default major number (97) that this driver
89*4882a593Smuzhiyun 			will use.  Be sure to change the device
90*4882a593Smuzhiyun 			name as well.
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	    name	This parameter is a character string that
93*4882a593Smuzhiyun 			contains the name the kernel will use for this
94*4882a593Smuzhiyun 			device (in /proc output, for instance).
95*4882a593Smuzhiyun 			(default "pg").
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	    verbose     This parameter controls the amount of logging
98*4882a593Smuzhiyun 			that is done by the driver.  Set it to 0 for
99*4882a593Smuzhiyun 			quiet operation, to 1 to enable progress
100*4882a593Smuzhiyun 			messages while the driver probes for devices,
101*4882a593Smuzhiyun 			or to 2 for full debug logging.  (default 0)
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	If this driver is built into the kernel, you can use
104*4882a593Smuzhiyun 	the following command line parameters, with the same values
105*4882a593Smuzhiyun 	as the corresponding module parameters listed above:
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	    pg.drive0
108*4882a593Smuzhiyun 	    pg.drive1
109*4882a593Smuzhiyun 	    pg.drive2
110*4882a593Smuzhiyun 	    pg.drive3
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	In addition, you can use the parameter pg.disable to disable
113*4882a593Smuzhiyun 	the driver entirely.
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun /* Changes:
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	1.01	GRG 1998.06.16	Bug fixes
120*4882a593Smuzhiyun 	1.02    GRG 1998.09.24  Added jumbo support
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun */
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun #define PG_VERSION      "1.02"
125*4882a593Smuzhiyun #define PG_MAJOR	97
126*4882a593Smuzhiyun #define PG_NAME		"pg"
127*4882a593Smuzhiyun #define PG_UNITS	4
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun #ifndef PI_PG
130*4882a593Smuzhiyun #define PI_PG	4
131*4882a593Smuzhiyun #endif
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun #include <linux/types.h>
134*4882a593Smuzhiyun /* Here are things one can override from the insmod command.
135*4882a593Smuzhiyun    Most are autoprobed by paride unless set here.  Verbose is 0
136*4882a593Smuzhiyun    by default.
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun */
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static int verbose;
141*4882a593Smuzhiyun static int major = PG_MAJOR;
142*4882a593Smuzhiyun static char *name = PG_NAME;
143*4882a593Smuzhiyun static int disable = 0;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
146*4882a593Smuzhiyun static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
147*4882a593Smuzhiyun static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
148*4882a593Smuzhiyun static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
151*4882a593Smuzhiyun static int pg_drive_count;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /* end of parameters */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #include <linux/module.h>
158*4882a593Smuzhiyun #include <linux/init.h>
159*4882a593Smuzhiyun #include <linux/fs.h>
160*4882a593Smuzhiyun #include <linux/delay.h>
161*4882a593Smuzhiyun #include <linux/slab.h>
162*4882a593Smuzhiyun #include <linux/mtio.h>
163*4882a593Smuzhiyun #include <linux/pg.h>
164*4882a593Smuzhiyun #include <linux/device.h>
165*4882a593Smuzhiyun #include <linux/sched.h>	/* current, TASK_* */
166*4882a593Smuzhiyun #include <linux/mutex.h>
167*4882a593Smuzhiyun #include <linux/jiffies.h>
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun #include <linux/uaccess.h>
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun module_param(verbose, int, 0644);
172*4882a593Smuzhiyun module_param(major, int, 0);
173*4882a593Smuzhiyun module_param(name, charp, 0);
174*4882a593Smuzhiyun module_param_array(drive0, int, NULL, 0);
175*4882a593Smuzhiyun module_param_array(drive1, int, NULL, 0);
176*4882a593Smuzhiyun module_param_array(drive2, int, NULL, 0);
177*4882a593Smuzhiyun module_param_array(drive3, int, NULL, 0);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun #include "paride.h"
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun #define PG_SPIN_DEL     50	/* spin delay in micro-seconds  */
182*4882a593Smuzhiyun #define PG_SPIN         200
183*4882a593Smuzhiyun #define PG_TMO		HZ
184*4882a593Smuzhiyun #define PG_RESET_TMO	10*HZ
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun #define STAT_ERR        0x01
187*4882a593Smuzhiyun #define STAT_INDEX      0x02
188*4882a593Smuzhiyun #define STAT_ECC        0x04
189*4882a593Smuzhiyun #define STAT_DRQ        0x08
190*4882a593Smuzhiyun #define STAT_SEEK       0x10
191*4882a593Smuzhiyun #define STAT_WRERR      0x20
192*4882a593Smuzhiyun #define STAT_READY      0x40
193*4882a593Smuzhiyun #define STAT_BUSY       0x80
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun #define ATAPI_IDENTIFY		0x12
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static DEFINE_MUTEX(pg_mutex);
198*4882a593Smuzhiyun static int pg_open(struct inode *inode, struct file *file);
199*4882a593Smuzhiyun static int pg_release(struct inode *inode, struct file *file);
200*4882a593Smuzhiyun static ssize_t pg_read(struct file *filp, char __user *buf,
201*4882a593Smuzhiyun 		       size_t count, loff_t * ppos);
202*4882a593Smuzhiyun static ssize_t pg_write(struct file *filp, const char __user *buf,
203*4882a593Smuzhiyun 			size_t count, loff_t * ppos);
204*4882a593Smuzhiyun static int pg_detect(void);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun #define PG_NAMELEN      8
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun struct pg {
209*4882a593Smuzhiyun 	struct pi_adapter pia;	/* interface to paride layer */
210*4882a593Smuzhiyun 	struct pi_adapter *pi;
211*4882a593Smuzhiyun 	int busy;		/* write done, read expected */
212*4882a593Smuzhiyun 	int start;		/* jiffies at command start */
213*4882a593Smuzhiyun 	int dlen;		/* transfer size requested */
214*4882a593Smuzhiyun 	unsigned long timeout;	/* timeout requested */
215*4882a593Smuzhiyun 	int status;		/* last sense key */
216*4882a593Smuzhiyun 	int drive;		/* drive */
217*4882a593Smuzhiyun 	unsigned long access;	/* count of active opens ... */
218*4882a593Smuzhiyun 	int present;		/* device present ? */
219*4882a593Smuzhiyun 	char *bufptr;
220*4882a593Smuzhiyun 	char name[PG_NAMELEN];	/* pg0, pg1, ... */
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static struct pg devices[PG_UNITS];
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun static int pg_identify(struct pg *dev, int log);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun static char pg_scratch[512];	/* scratch block buffer */
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static struct class *pg_class;
230*4882a593Smuzhiyun static void *par_drv;		/* reference of parport driver */
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /* kernel glue structures */
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun static const struct file_operations pg_fops = {
235*4882a593Smuzhiyun 	.owner = THIS_MODULE,
236*4882a593Smuzhiyun 	.read = pg_read,
237*4882a593Smuzhiyun 	.write = pg_write,
238*4882a593Smuzhiyun 	.open = pg_open,
239*4882a593Smuzhiyun 	.release = pg_release,
240*4882a593Smuzhiyun 	.llseek = noop_llseek,
241*4882a593Smuzhiyun };
242*4882a593Smuzhiyun 
pg_init_units(void)243*4882a593Smuzhiyun static void pg_init_units(void)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	int unit;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	pg_drive_count = 0;
248*4882a593Smuzhiyun 	for (unit = 0; unit < PG_UNITS; unit++) {
249*4882a593Smuzhiyun 		int *parm = *drives[unit];
250*4882a593Smuzhiyun 		struct pg *dev = &devices[unit];
251*4882a593Smuzhiyun 		dev->pi = &dev->pia;
252*4882a593Smuzhiyun 		clear_bit(0, &dev->access);
253*4882a593Smuzhiyun 		dev->busy = 0;
254*4882a593Smuzhiyun 		dev->present = 0;
255*4882a593Smuzhiyun 		dev->bufptr = NULL;
256*4882a593Smuzhiyun 		dev->drive = parm[D_SLV];
257*4882a593Smuzhiyun 		snprintf(dev->name, PG_NAMELEN, "%s%c", name, 'a'+unit);
258*4882a593Smuzhiyun 		if (parm[D_PRT])
259*4882a593Smuzhiyun 			pg_drive_count++;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
status_reg(struct pg * dev)263*4882a593Smuzhiyun static inline int status_reg(struct pg *dev)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	return pi_read_regr(dev->pi, 1, 6);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
read_reg(struct pg * dev,int reg)268*4882a593Smuzhiyun static inline int read_reg(struct pg *dev, int reg)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	return pi_read_regr(dev->pi, 0, reg);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
write_reg(struct pg * dev,int reg,int val)273*4882a593Smuzhiyun static inline void write_reg(struct pg *dev, int reg, int val)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	pi_write_regr(dev->pi, 0, reg, val);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
DRIVE(struct pg * dev)278*4882a593Smuzhiyun static inline u8 DRIVE(struct pg *dev)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	return 0xa0+0x10*dev->drive;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
pg_sleep(int cs)283*4882a593Smuzhiyun static void pg_sleep(int cs)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	schedule_timeout_interruptible(cs);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
pg_wait(struct pg * dev,int go,int stop,unsigned long tmo,char * msg)288*4882a593Smuzhiyun static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	int j, r, e, s, p, to;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	dev->status = 0;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	j = 0;
295*4882a593Smuzhiyun 	while ((((r = status_reg(dev)) & go) || (stop && (!(r & stop))))
296*4882a593Smuzhiyun 	       && time_before(jiffies, tmo)) {
297*4882a593Smuzhiyun 		if (j++ < PG_SPIN)
298*4882a593Smuzhiyun 			udelay(PG_SPIN_DEL);
299*4882a593Smuzhiyun 		else
300*4882a593Smuzhiyun 			pg_sleep(1);
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	to = time_after_eq(jiffies, tmo);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	if ((r & (STAT_ERR & stop)) || to) {
306*4882a593Smuzhiyun 		s = read_reg(dev, 7);
307*4882a593Smuzhiyun 		e = read_reg(dev, 1);
308*4882a593Smuzhiyun 		p = read_reg(dev, 2);
309*4882a593Smuzhiyun 		if (verbose > 1)
310*4882a593Smuzhiyun 			printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
311*4882a593Smuzhiyun 			       dev->name, msg, s, e, p, to ? " timeout" : "");
312*4882a593Smuzhiyun 		if (to)
313*4882a593Smuzhiyun 			e |= 0x100;
314*4882a593Smuzhiyun 		dev->status = (e >> 4) & 0xff;
315*4882a593Smuzhiyun 		return -1;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 	return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
pg_command(struct pg * dev,char * cmd,int dlen,unsigned long tmo)320*4882a593Smuzhiyun static int pg_command(struct pg *dev, char *cmd, int dlen, unsigned long tmo)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	int k;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	pi_connect(dev->pi);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	write_reg(dev, 6, DRIVE(dev));
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	if (pg_wait(dev, STAT_BUSY | STAT_DRQ, 0, tmo, "before command"))
329*4882a593Smuzhiyun 		goto fail;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	write_reg(dev, 4, dlen % 256);
332*4882a593Smuzhiyun 	write_reg(dev, 5, dlen / 256);
333*4882a593Smuzhiyun 	write_reg(dev, 7, 0xa0);	/* ATAPI packet command */
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (pg_wait(dev, STAT_BUSY, STAT_DRQ, tmo, "command DRQ"))
336*4882a593Smuzhiyun 		goto fail;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (read_reg(dev, 2) != 1) {
339*4882a593Smuzhiyun 		printk("%s: command phase error\n", dev->name);
340*4882a593Smuzhiyun 		goto fail;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	pi_write_block(dev->pi, cmd, 12);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	if (verbose > 1) {
346*4882a593Smuzhiyun 		printk("%s: Command sent, dlen=%d packet= ", dev->name, dlen);
347*4882a593Smuzhiyun 		for (k = 0; k < 12; k++)
348*4882a593Smuzhiyun 			printk("%02x ", cmd[k] & 0xff);
349*4882a593Smuzhiyun 		printk("\n");
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 	return 0;
352*4882a593Smuzhiyun fail:
353*4882a593Smuzhiyun 	pi_disconnect(dev->pi);
354*4882a593Smuzhiyun 	return -1;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
pg_completion(struct pg * dev,char * buf,unsigned long tmo)357*4882a593Smuzhiyun static int pg_completion(struct pg *dev, char *buf, unsigned long tmo)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	int r, d, n, p;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
362*4882a593Smuzhiyun 		    tmo, "completion");
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	dev->dlen = 0;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	while (read_reg(dev, 7) & STAT_DRQ) {
367*4882a593Smuzhiyun 		d = (read_reg(dev, 4) + 256 * read_reg(dev, 5));
368*4882a593Smuzhiyun 		n = ((d + 3) & 0xfffc);
369*4882a593Smuzhiyun 		p = read_reg(dev, 2) & 3;
370*4882a593Smuzhiyun 		if (p == 0)
371*4882a593Smuzhiyun 			pi_write_block(dev->pi, buf, n);
372*4882a593Smuzhiyun 		if (p == 2)
373*4882a593Smuzhiyun 			pi_read_block(dev->pi, buf, n);
374*4882a593Smuzhiyun 		if (verbose > 1)
375*4882a593Smuzhiyun 			printk("%s: %s %d bytes\n", dev->name,
376*4882a593Smuzhiyun 			       p ? "Read" : "Write", n);
377*4882a593Smuzhiyun 		dev->dlen += (1 - p) * d;
378*4882a593Smuzhiyun 		buf += d;
379*4882a593Smuzhiyun 		r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
380*4882a593Smuzhiyun 			    tmo, "completion");
381*4882a593Smuzhiyun 	}
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	pi_disconnect(dev->pi);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	return r;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
pg_reset(struct pg * dev)388*4882a593Smuzhiyun static int pg_reset(struct pg *dev)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	int i, k, err;
391*4882a593Smuzhiyun 	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
392*4882a593Smuzhiyun 	int got[5];
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	pi_connect(dev->pi);
395*4882a593Smuzhiyun 	write_reg(dev, 6, DRIVE(dev));
396*4882a593Smuzhiyun 	write_reg(dev, 7, 8);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	pg_sleep(20 * HZ / 1000);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	k = 0;
401*4882a593Smuzhiyun 	while ((k++ < PG_RESET_TMO) && (status_reg(dev) & STAT_BUSY))
402*4882a593Smuzhiyun 		pg_sleep(1);
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	for (i = 0; i < 5; i++)
405*4882a593Smuzhiyun 		got[i] = read_reg(dev, i + 1);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	err = memcmp(expect, got, sizeof(got)) ? -1 : 0;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	if (verbose) {
410*4882a593Smuzhiyun 		printk("%s: Reset (%d) signature = ", dev->name, k);
411*4882a593Smuzhiyun 		for (i = 0; i < 5; i++)
412*4882a593Smuzhiyun 			printk("%3x", got[i]);
413*4882a593Smuzhiyun 		if (err)
414*4882a593Smuzhiyun 			printk(" (incorrect)");
415*4882a593Smuzhiyun 		printk("\n");
416*4882a593Smuzhiyun 	}
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	pi_disconnect(dev->pi);
419*4882a593Smuzhiyun 	return err;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
xs(char * buf,char * targ,int len)422*4882a593Smuzhiyun static void xs(char *buf, char *targ, int len)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	char l = '\0';
425*4882a593Smuzhiyun 	int k;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	for (k = 0; k < len; k++) {
428*4882a593Smuzhiyun 		char c = *buf++;
429*4882a593Smuzhiyun 		if (c != ' ' && c != l)
430*4882a593Smuzhiyun 			l = *targ++ = c;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 	if (l == ' ')
433*4882a593Smuzhiyun 		targ--;
434*4882a593Smuzhiyun 	*targ = '\0';
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
pg_identify(struct pg * dev,int log)437*4882a593Smuzhiyun static int pg_identify(struct pg *dev, int log)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	int s;
440*4882a593Smuzhiyun 	char *ms[2] = { "master", "slave" };
441*4882a593Smuzhiyun 	char mf[10], id[18];
442*4882a593Smuzhiyun 	char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
443*4882a593Smuzhiyun 	char buf[36];
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	s = pg_command(dev, id_cmd, 36, jiffies + PG_TMO);
446*4882a593Smuzhiyun 	if (s)
447*4882a593Smuzhiyun 		return -1;
448*4882a593Smuzhiyun 	s = pg_completion(dev, buf, jiffies + PG_TMO);
449*4882a593Smuzhiyun 	if (s)
450*4882a593Smuzhiyun 		return -1;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (log) {
453*4882a593Smuzhiyun 		xs(buf + 8, mf, 8);
454*4882a593Smuzhiyun 		xs(buf + 16, id, 16);
455*4882a593Smuzhiyun 		printk("%s: %s %s, %s\n", dev->name, mf, id, ms[dev->drive]);
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	return 0;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun  * returns  0, with id set if drive is detected
463*4882a593Smuzhiyun  *	   -1, if drive detection failed
464*4882a593Smuzhiyun  */
pg_probe(struct pg * dev)465*4882a593Smuzhiyun static int pg_probe(struct pg *dev)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	if (dev->drive == -1) {
468*4882a593Smuzhiyun 		for (dev->drive = 0; dev->drive <= 1; dev->drive++)
469*4882a593Smuzhiyun 			if (!pg_reset(dev))
470*4882a593Smuzhiyun 				return pg_identify(dev, 1);
471*4882a593Smuzhiyun 	} else {
472*4882a593Smuzhiyun 		if (!pg_reset(dev))
473*4882a593Smuzhiyun 			return pg_identify(dev, 1);
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 	return -1;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
pg_detect(void)478*4882a593Smuzhiyun static int pg_detect(void)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun 	struct pg *dev = &devices[0];
481*4882a593Smuzhiyun 	int k, unit;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	printk("%s: %s version %s, major %d\n", name, name, PG_VERSION, major);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	par_drv = pi_register_driver(name);
486*4882a593Smuzhiyun 	if (!par_drv) {
487*4882a593Smuzhiyun 		pr_err("failed to register %s driver\n", name);
488*4882a593Smuzhiyun 		return -1;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	k = 0;
492*4882a593Smuzhiyun 	if (pg_drive_count == 0) {
493*4882a593Smuzhiyun 		if (pi_init(dev->pi, 1, -1, -1, -1, -1, -1, pg_scratch,
494*4882a593Smuzhiyun 			    PI_PG, verbose, dev->name)) {
495*4882a593Smuzhiyun 			if (!pg_probe(dev)) {
496*4882a593Smuzhiyun 				dev->present = 1;
497*4882a593Smuzhiyun 				k++;
498*4882a593Smuzhiyun 			} else
499*4882a593Smuzhiyun 				pi_release(dev->pi);
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	} else
503*4882a593Smuzhiyun 		for (unit = 0; unit < PG_UNITS; unit++, dev++) {
504*4882a593Smuzhiyun 			int *parm = *drives[unit];
505*4882a593Smuzhiyun 			if (!parm[D_PRT])
506*4882a593Smuzhiyun 				continue;
507*4882a593Smuzhiyun 			if (pi_init(dev->pi, 0, parm[D_PRT], parm[D_MOD],
508*4882a593Smuzhiyun 				    parm[D_UNI], parm[D_PRO], parm[D_DLY],
509*4882a593Smuzhiyun 				    pg_scratch, PI_PG, verbose, dev->name)) {
510*4882a593Smuzhiyun 				if (!pg_probe(dev)) {
511*4882a593Smuzhiyun 					dev->present = 1;
512*4882a593Smuzhiyun 					k++;
513*4882a593Smuzhiyun 				} else
514*4882a593Smuzhiyun 					pi_release(dev->pi);
515*4882a593Smuzhiyun 			}
516*4882a593Smuzhiyun 		}
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	if (k)
519*4882a593Smuzhiyun 		return 0;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	pi_unregister_driver(par_drv);
522*4882a593Smuzhiyun 	printk("%s: No ATAPI device detected\n", name);
523*4882a593Smuzhiyun 	return -1;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
pg_open(struct inode * inode,struct file * file)526*4882a593Smuzhiyun static int pg_open(struct inode *inode, struct file *file)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun 	int unit = iminor(inode) & 0x7f;
529*4882a593Smuzhiyun 	struct pg *dev = &devices[unit];
530*4882a593Smuzhiyun 	int ret = 0;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	mutex_lock(&pg_mutex);
533*4882a593Smuzhiyun 	if ((unit >= PG_UNITS) || (!dev->present)) {
534*4882a593Smuzhiyun 		ret = -ENODEV;
535*4882a593Smuzhiyun 		goto out;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	if (test_and_set_bit(0, &dev->access)) {
539*4882a593Smuzhiyun 		ret = -EBUSY;
540*4882a593Smuzhiyun 		goto out;
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	if (dev->busy) {
544*4882a593Smuzhiyun 		pg_reset(dev);
545*4882a593Smuzhiyun 		dev->busy = 0;
546*4882a593Smuzhiyun 	}
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	pg_identify(dev, (verbose > 1));
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	dev->bufptr = kmalloc(PG_MAX_DATA, GFP_KERNEL);
551*4882a593Smuzhiyun 	if (dev->bufptr == NULL) {
552*4882a593Smuzhiyun 		clear_bit(0, &dev->access);
553*4882a593Smuzhiyun 		printk("%s: buffer allocation failed\n", dev->name);
554*4882a593Smuzhiyun 		ret = -ENOMEM;
555*4882a593Smuzhiyun 		goto out;
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	file->private_data = dev;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun out:
561*4882a593Smuzhiyun 	mutex_unlock(&pg_mutex);
562*4882a593Smuzhiyun 	return ret;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun 
pg_release(struct inode * inode,struct file * file)565*4882a593Smuzhiyun static int pg_release(struct inode *inode, struct file *file)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	struct pg *dev = file->private_data;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	kfree(dev->bufptr);
570*4882a593Smuzhiyun 	dev->bufptr = NULL;
571*4882a593Smuzhiyun 	clear_bit(0, &dev->access);
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	return 0;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
pg_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)576*4882a593Smuzhiyun static ssize_t pg_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun 	struct pg *dev = filp->private_data;
579*4882a593Smuzhiyun 	struct pg_write_hdr hdr;
580*4882a593Smuzhiyun 	int hs = sizeof (hdr);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	if (dev->busy)
583*4882a593Smuzhiyun 		return -EBUSY;
584*4882a593Smuzhiyun 	if (count < hs)
585*4882a593Smuzhiyun 		return -EINVAL;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	if (copy_from_user(&hdr, buf, hs))
588*4882a593Smuzhiyun 		return -EFAULT;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	if (hdr.magic != PG_MAGIC)
591*4882a593Smuzhiyun 		return -EINVAL;
592*4882a593Smuzhiyun 	if (hdr.dlen < 0 || hdr.dlen > PG_MAX_DATA)
593*4882a593Smuzhiyun 		return -EINVAL;
594*4882a593Smuzhiyun 	if ((count - hs) > PG_MAX_DATA)
595*4882a593Smuzhiyun 		return -EINVAL;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if (hdr.func == PG_RESET) {
598*4882a593Smuzhiyun 		if (count != hs)
599*4882a593Smuzhiyun 			return -EINVAL;
600*4882a593Smuzhiyun 		if (pg_reset(dev))
601*4882a593Smuzhiyun 			return -EIO;
602*4882a593Smuzhiyun 		return count;
603*4882a593Smuzhiyun 	}
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	if (hdr.func != PG_COMMAND)
606*4882a593Smuzhiyun 		return -EINVAL;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	dev->start = jiffies;
609*4882a593Smuzhiyun 	dev->timeout = hdr.timeout * HZ + HZ / 2 + jiffies;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	if (pg_command(dev, hdr.packet, hdr.dlen, jiffies + PG_TMO)) {
612*4882a593Smuzhiyun 		if (dev->status & 0x10)
613*4882a593Smuzhiyun 			return -ETIME;
614*4882a593Smuzhiyun 		return -EIO;
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	dev->busy = 1;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	if (copy_from_user(dev->bufptr, buf + hs, count - hs))
620*4882a593Smuzhiyun 		return -EFAULT;
621*4882a593Smuzhiyun 	return count;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
pg_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)624*4882a593Smuzhiyun static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	struct pg *dev = filp->private_data;
627*4882a593Smuzhiyun 	struct pg_read_hdr hdr;
628*4882a593Smuzhiyun 	int hs = sizeof (hdr);
629*4882a593Smuzhiyun 	int copy;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	if (!dev->busy)
632*4882a593Smuzhiyun 		return -EINVAL;
633*4882a593Smuzhiyun 	if (count < hs)
634*4882a593Smuzhiyun 		return -EINVAL;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	dev->busy = 0;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	if (pg_completion(dev, dev->bufptr, dev->timeout))
639*4882a593Smuzhiyun 		if (dev->status & 0x10)
640*4882a593Smuzhiyun 			return -ETIME;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	memset(&hdr, 0, sizeof(hdr));
643*4882a593Smuzhiyun 	hdr.magic = PG_MAGIC;
644*4882a593Smuzhiyun 	hdr.dlen = dev->dlen;
645*4882a593Smuzhiyun 	copy = 0;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	if (hdr.dlen < 0) {
648*4882a593Smuzhiyun 		hdr.dlen = -1 * hdr.dlen;
649*4882a593Smuzhiyun 		copy = hdr.dlen;
650*4882a593Smuzhiyun 		if (copy > (count - hs))
651*4882a593Smuzhiyun 			copy = count - hs;
652*4882a593Smuzhiyun 	}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	hdr.duration = (jiffies - dev->start + HZ / 2) / HZ;
655*4882a593Smuzhiyun 	hdr.scsi = dev->status & 0x0f;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	if (copy_to_user(buf, &hdr, hs))
658*4882a593Smuzhiyun 		return -EFAULT;
659*4882a593Smuzhiyun 	if (copy > 0)
660*4882a593Smuzhiyun 		if (copy_to_user(buf + hs, dev->bufptr, copy))
661*4882a593Smuzhiyun 			return -EFAULT;
662*4882a593Smuzhiyun 	return copy + hs;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun 
pg_init(void)665*4882a593Smuzhiyun static int __init pg_init(void)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	int unit;
668*4882a593Smuzhiyun 	int err;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (disable){
671*4882a593Smuzhiyun 		err = -EINVAL;
672*4882a593Smuzhiyun 		goto out;
673*4882a593Smuzhiyun 	}
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	pg_init_units();
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (pg_detect()) {
678*4882a593Smuzhiyun 		err = -ENODEV;
679*4882a593Smuzhiyun 		goto out;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	err = register_chrdev(major, name, &pg_fops);
683*4882a593Smuzhiyun 	if (err < 0) {
684*4882a593Smuzhiyun 		printk("pg_init: unable to get major number %d\n", major);
685*4882a593Smuzhiyun 		for (unit = 0; unit < PG_UNITS; unit++) {
686*4882a593Smuzhiyun 			struct pg *dev = &devices[unit];
687*4882a593Smuzhiyun 			if (dev->present)
688*4882a593Smuzhiyun 				pi_release(dev->pi);
689*4882a593Smuzhiyun 		}
690*4882a593Smuzhiyun 		goto out;
691*4882a593Smuzhiyun 	}
692*4882a593Smuzhiyun 	major = err;	/* In case the user specified `major=0' (dynamic) */
693*4882a593Smuzhiyun 	pg_class = class_create(THIS_MODULE, "pg");
694*4882a593Smuzhiyun 	if (IS_ERR(pg_class)) {
695*4882a593Smuzhiyun 		err = PTR_ERR(pg_class);
696*4882a593Smuzhiyun 		goto out_chrdev;
697*4882a593Smuzhiyun 	}
698*4882a593Smuzhiyun 	for (unit = 0; unit < PG_UNITS; unit++) {
699*4882a593Smuzhiyun 		struct pg *dev = &devices[unit];
700*4882a593Smuzhiyun 		if (dev->present)
701*4882a593Smuzhiyun 			device_create(pg_class, NULL, MKDEV(major, unit), NULL,
702*4882a593Smuzhiyun 				      "pg%u", unit);
703*4882a593Smuzhiyun 	}
704*4882a593Smuzhiyun 	err = 0;
705*4882a593Smuzhiyun 	goto out;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun out_chrdev:
708*4882a593Smuzhiyun 	unregister_chrdev(major, "pg");
709*4882a593Smuzhiyun out:
710*4882a593Smuzhiyun 	return err;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
pg_exit(void)713*4882a593Smuzhiyun static void __exit pg_exit(void)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun 	int unit;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	for (unit = 0; unit < PG_UNITS; unit++) {
718*4882a593Smuzhiyun 		struct pg *dev = &devices[unit];
719*4882a593Smuzhiyun 		if (dev->present)
720*4882a593Smuzhiyun 			device_destroy(pg_class, MKDEV(major, unit));
721*4882a593Smuzhiyun 	}
722*4882a593Smuzhiyun 	class_destroy(pg_class);
723*4882a593Smuzhiyun 	unregister_chrdev(major, name);
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	for (unit = 0; unit < PG_UNITS; unit++) {
726*4882a593Smuzhiyun 		struct pg *dev = &devices[unit];
727*4882a593Smuzhiyun 		if (dev->present)
728*4882a593Smuzhiyun 			pi_release(dev->pi);
729*4882a593Smuzhiyun 	}
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun MODULE_LICENSE("GPL");
733*4882a593Smuzhiyun module_init(pg_init)
734*4882a593Smuzhiyun module_exit(pg_exit)
735