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