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