2 pt.c (c) 1998 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU General Public License.
5 This is the high-level driver for parallel port ATAPI tape
6 drives based on chips supported by the paride module.
8 The driver implements both rewinding and non-rewinding
9 devices, filemarks, and the rewind ioctl. It allocates
10 a small internal "bounce buffer" for each open device, but
11 otherwise expects buffering and blocking to be done at the
12 user level. As with most block-structured tapes, short
13 writes are padded to full tape blocks, so reading back a file
14 may return more data than was actually written.
16 By default, the driver will autoprobe for a single parallel
17 port ATAPI tape drive, but if their individual parameters are
18 specified, the driver can handle up to 4 drives.
20 The rewinding devices are named /dev/pt0, /dev/pt1, ...
21 while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
23 The behaviour of the pt driver can be altered by setting
24 some parameters from the insmod command line. The following
25 parameters are adjustable:
27 drive0 These four arguments can be arrays of
28 drive1 1-6 integers as follows:
30 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
34 <prt> is the base of the parallel port address for
35 the corresponding drive. (required)
37 <pro> is the protocol number for the adapter that
38 supports this drive. These numbers are
39 logged by 'paride' when the protocol modules
40 are initialised. (0 if not given)
42 <uni> for those adapters that support chained
43 devices, this is the unit selector for the
44 chain of devices on the given port. It should
45 be zero for devices that don't support chaining.
48 <mod> this can be -1 to choose the best mode, or one
49 of the mode numbers supported by the adapter.
52 <slv> ATAPI devices can be jumpered to master or slave.
53 Set this to 0 to choose the master drive, 1 to
54 choose the slave, -1 (the default) to choose the
57 <dly> some parallel ports require the driver to
58 go more slowly. -1 sets a default value that
59 should work with the chosen protocol. Otherwise,
60 set this to a small integer, the larger it is
61 the slower the port i/o. In some cases, setting
62 this to zero will speed up the device. (default -1)
64 major You may use this parameter to overide the
65 default major number (96) that this driver
66 will use. Be sure to change the device
69 name This parameter is a character string that
70 contains the name the kernel will use for this
71 device (in /proc output, for instance).
74 verbose This parameter controls the amount of logging
75 that the driver will do. Set it to 0 for
76 normal operation, 1 to see autoprobe progress
77 messages, or 2 to see additional debugging
80 If this driver is built into the kernel, you can use
81 the following command line parameters, with the same values
82 as the corresponding module parameters listed above:
89 In addition, you can use the parameter pt.disable to disable
96 1.01 GRG 1998.05.06 Round up transfer size, fix ready_wait,
97 loosed interpretation of ATAPI standard
98 for clearing error status.
100 1.02 GRG 1998.06.16 Eliminate an Ugh.
101 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing,
103 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support
107 #define PT_VERSION "1.04"
112 #include <linux/types.h>
114 /* Here are things one can override from the insmod command.
115 Most are autoprobed by paride unless set here. Verbose is on
120 static int verbose
= 0;
121 static int major
= PT_MAJOR
;
122 static char *name
= PT_NAME
;
123 static int disable
= 0;
125 static int drive0
[6] = { 0, 0, 0, -1, -1, -1 };
126 static int drive1
[6] = { 0, 0, 0, -1, -1, -1 };
127 static int drive2
[6] = { 0, 0, 0, -1, -1, -1 };
128 static int drive3
[6] = { 0, 0, 0, -1, -1, -1 };
130 static int (*drives
[4])[6] = {&drive0
, &drive1
, &drive2
, &drive3
};
139 #define DU (*drives[unit])
141 /* end of parameters */
143 #include <linux/module.h>
144 #include <linux/init.h>
145 #include <linux/fs.h>
146 #include <linux/delay.h>
147 #include <linux/slab.h>
148 #include <linux/mtio.h>
149 #include <linux/device.h>
150 #include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
151 #include <linux/mutex.h>
153 #include <linux/uaccess.h>
155 module_param(verbose
, int, 0);
156 module_param(major
, int, 0);
157 module_param(name
, charp
, 0);
158 module_param_array(drive0
, int, NULL
, 0);
159 module_param_array(drive1
, int, NULL
, 0);
160 module_param_array(drive2
, int, NULL
, 0);
161 module_param_array(drive3
, int, NULL
, 0);
165 #define PT_MAX_RETRIES 5
166 #define PT_TMO 3000 /* interrupt timeout in jiffies */
167 #define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
168 #define PT_RESET_TMO 30 /* 30 seconds */
169 #define PT_READY_TMO 60 /* 60 seconds */
170 #define PT_REWIND_TMO 1200 /* 20 minutes */
172 #define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
174 #define STAT_ERR 0x00001
175 #define STAT_INDEX 0x00002
176 #define STAT_ECC 0x00004
177 #define STAT_DRQ 0x00008
178 #define STAT_SEEK 0x00010
179 #define STAT_WRERR 0x00020
180 #define STAT_READY 0x00040
181 #define STAT_BUSY 0x00080
182 #define STAT_SENSE 0x1f000
184 #define ATAPI_TEST_READY 0x00
185 #define ATAPI_REWIND 0x01
186 #define ATAPI_REQ_SENSE 0x03
187 #define ATAPI_READ_6 0x08
188 #define ATAPI_WRITE_6 0x0a
189 #define ATAPI_WFM 0x10
190 #define ATAPI_IDENTIFY 0x12
191 #define ATAPI_MODE_SENSE 0x1a
192 #define ATAPI_LOG_SENSE 0x4d
194 static DEFINE_MUTEX(pt_mutex
);
195 static int pt_open(struct inode
*inode
, struct file
*file
);
196 static long pt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
);
197 static int pt_release(struct inode
*inode
, struct file
*file
);
198 static ssize_t
pt_read(struct file
*filp
, char __user
*buf
,
199 size_t count
, loff_t
* ppos
);
200 static ssize_t
pt_write(struct file
*filp
, const char __user
*buf
,
201 size_t count
, loff_t
* ppos
);
202 static int pt_detect(void);
204 /* bits in tape->flags */
207 #define PT_WRITE_OK 2
210 #define PT_READING 16
214 #define PT_BUFSIZE 16384
217 struct pi_adapter pia
; /* interface to paride layer */
218 struct pi_adapter
*pi
;
219 int flags
; /* various state flags */
220 int last_sense
; /* result of last request sense */
221 int drive
; /* drive */
222 atomic_t available
; /* 1 if access is available 0 otherwise */
223 int bs
; /* block size */
224 int capacity
; /* Size of tape in KB */
225 int present
; /* device present ? */
227 char name
[PT_NAMELEN
]; /* pf0, pf1, ... */
230 static int pt_identify(struct pt_unit
*tape
);
232 static struct pt_unit pt
[PT_UNITS
];
234 static char pt_scratch
[512]; /* scratch block buffer */
235 static void *par_drv
; /* reference of parport driver */
237 /* kernel glue structures */
239 static const struct file_operations pt_fops
= {
240 .owner
= THIS_MODULE
,
243 .unlocked_ioctl
= pt_ioctl
,
245 .release
= pt_release
,
246 .llseek
= noop_llseek
,
249 /* sysfs class support */
250 static struct class *pt_class
;
252 static inline int status_reg(struct pi_adapter
*pi
)
254 return pi_read_regr(pi
, 1, 6);
257 static inline int read_reg(struct pi_adapter
*pi
, int reg
)
259 return pi_read_regr(pi
, 0, reg
);
262 static inline void write_reg(struct pi_adapter
*pi
, int reg
, int val
)
264 pi_write_regr(pi
, 0, reg
, val
);
267 static inline u8
DRIVE(struct pt_unit
*tape
)
269 return 0xa0+0x10*tape
->drive
;
272 static int pt_wait(struct pt_unit
*tape
, int go
, int stop
, char *fun
, char *msg
)
275 struct pi_adapter
*pi
= tape
->pi
;
278 while ((((r
= status_reg(pi
)) & go
) || (stop
&& (!(r
& stop
))))
282 if ((r
& (STAT_ERR
& stop
)) || (j
> PT_SPIN
)) {
289 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
290 " loop=%d phase=%d\n",
291 tape
->name
, fun
, msg
, r
, s
, e
, j
, p
);
297 static int pt_command(struct pt_unit
*tape
, char *cmd
, int dlen
, char *fun
)
299 struct pi_adapter
*pi
= tape
->pi
;
302 write_reg(pi
, 6, DRIVE(tape
));
304 if (pt_wait(tape
, STAT_BUSY
| STAT_DRQ
, 0, fun
, "before command")) {
309 write_reg(pi
, 4, dlen
% 256);
310 write_reg(pi
, 5, dlen
/ 256);
311 write_reg(pi
, 7, 0xa0); /* ATAPI packet command */
313 if (pt_wait(tape
, STAT_BUSY
, STAT_DRQ
, fun
, "command DRQ")) {
318 if (read_reg(pi
, 2) != 1) {
319 printk("%s: %s: command phase error\n", tape
->name
, fun
);
324 pi_write_block(pi
, cmd
, 12);
329 static int pt_completion(struct pt_unit
*tape
, char *buf
, char *fun
)
331 struct pi_adapter
*pi
= tape
->pi
;
334 r
= pt_wait(tape
, STAT_BUSY
, STAT_DRQ
| STAT_READY
| STAT_ERR
,
337 if (read_reg(pi
, 7) & STAT_DRQ
) {
338 n
= (((read_reg(pi
, 4) + 256 * read_reg(pi
, 5)) +
340 p
= read_reg(pi
, 2) & 3;
342 pi_write_block(pi
, buf
, n
);
344 pi_read_block(pi
, buf
, n
);
347 s
= pt_wait(tape
, STAT_BUSY
, STAT_READY
| STAT_ERR
, fun
, "data done");
354 static void pt_req_sense(struct pt_unit
*tape
, int quiet
)
356 char rs_cmd
[12] = { ATAPI_REQ_SENSE
, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
360 r
= pt_command(tape
, rs_cmd
, 16, "Request sense");
363 pt_completion(tape
, buf
, "Request sense");
365 tape
->last_sense
= -1;
368 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
369 tape
->name
, buf
[2] & 0xf, buf
[12], buf
[13]);
370 tape
->last_sense
= (buf
[2] & 0xf) | ((buf
[12] & 0xff) << 8)
371 | ((buf
[13] & 0xff) << 16);
375 static int pt_atapi(struct pt_unit
*tape
, char *cmd
, int dlen
, char *buf
, char *fun
)
379 r
= pt_command(tape
, cmd
, dlen
, fun
);
382 r
= pt_completion(tape
, buf
, fun
);
384 pt_req_sense(tape
, !fun
);
389 static void pt_sleep(int cs
)
391 schedule_timeout_interruptible(cs
);
394 static int pt_poll_dsc(struct pt_unit
*tape
, int pause
, int tmo
, char *msg
)
396 struct pi_adapter
*pi
= tape
->pi
;
406 write_reg(pi
, 6, DRIVE(tape
));
410 if (s
& (STAT_ERR
| STAT_SEEK
))
413 if ((k
>= tmo
) || (s
& STAT_ERR
)) {
415 printk("%s: %s DSC timeout\n", tape
->name
, msg
);
417 printk("%s: %s stat=0x%x err=0x%x\n", tape
->name
, msg
, s
,
419 pt_req_sense(tape
, 0);
425 static void pt_media_access_cmd(struct pt_unit
*tape
, int tmo
, char *cmd
, char *fun
)
427 if (pt_command(tape
, cmd
, 0, fun
)) {
428 pt_req_sense(tape
, 0);
431 pi_disconnect(tape
->pi
);
432 pt_poll_dsc(tape
, HZ
, tmo
, fun
);
435 static void pt_rewind(struct pt_unit
*tape
)
437 char rw_cmd
[12] = { ATAPI_REWIND
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
439 pt_media_access_cmd(tape
, PT_REWIND_TMO
, rw_cmd
, "rewind");
442 static void pt_write_fm(struct pt_unit
*tape
)
444 char wm_cmd
[12] = { ATAPI_WFM
, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
446 pt_media_access_cmd(tape
, PT_TMO
, wm_cmd
, "write filemark");
449 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
451 static int pt_reset(struct pt_unit
*tape
)
453 struct pi_adapter
*pi
= tape
->pi
;
455 int expect
[5] = { 1, 1, 1, 0x14, 0xeb };
458 write_reg(pi
, 6, DRIVE(tape
));
461 pt_sleep(20 * HZ
/ 1000);
464 while ((k
++ < PT_RESET_TMO
) && (status_reg(pi
) & STAT_BUSY
))
468 for (i
= 0; i
< 5; i
++)
469 flg
&= (read_reg(pi
, i
+ 1) == expect
[i
]);
472 printk("%s: Reset (%d) signature = ", tape
->name
, k
);
473 for (i
= 0; i
< 5; i
++)
474 printk("%3x", read_reg(pi
, i
+ 1));
476 printk(" (incorrect)");
484 static int pt_ready_wait(struct pt_unit
*tape
, int tmo
)
486 char tr_cmd
[12] = { ATAPI_TEST_READY
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
491 tape
->last_sense
= 0;
492 pt_atapi(tape
, tr_cmd
, 0, NULL
, DBMSG("test unit ready"));
493 p
= tape
->last_sense
;
496 if (!(((p
& 0xffff) == 0x0402) || ((p
& 0xff) == 6)))
501 return 0x000020; /* timeout */
504 static void xs(char *buf
, char *targ
, int offs
, int len
)
510 for (k
= 0; k
< len
; k
++)
511 if ((buf
[k
+ offs
] != 0x20) || (buf
[k
+ offs
] != l
))
512 l
= targ
[j
++] = buf
[k
+ offs
];
518 static int xn(char *buf
, int offs
, int size
)
523 for (k
= 0; k
< size
; k
++)
524 v
= v
* 256 + (buf
[k
+ offs
] & 0xff);
528 static int pt_identify(struct pt_unit
*tape
)
531 char *ms
[2] = { "master", "slave" };
533 char id_cmd
[12] = { ATAPI_IDENTIFY
, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
535 { ATAPI_MODE_SENSE
, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
537 { ATAPI_LOG_SENSE
, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
540 s
= pt_atapi(tape
, id_cmd
, 36, buf
, "identify");
547 printk("%s: Drive %d, unsupported type %d\n",
548 tape
->name
, tape
->drive
, dt
);
559 if (!pt_ready_wait(tape
, PT_READY_TMO
))
560 tape
->flags
|= PT_MEDIA
;
562 if (!pt_atapi(tape
, ms_cmd
, 36, buf
, "mode sense")) {
563 if (!(buf
[2] & 0x80))
564 tape
->flags
|= PT_WRITE_OK
;
565 tape
->bs
= xn(buf
, 10, 2);
568 if (!pt_atapi(tape
, ls_cmd
, 36, buf
, "log sense"))
569 tape
->capacity
= xn(buf
, 24, 4);
571 printk("%s: %s %s, %s", tape
->name
, mf
, id
, ms
[tape
->drive
]);
572 if (!(tape
->flags
& PT_MEDIA
))
573 printk(", no media\n");
575 if (!(tape
->flags
& PT_WRITE_OK
))
577 printk(", blocksize %d, %d MB\n", tape
->bs
, tape
->capacity
/ 1024);
585 * returns 0, with id set if drive is detected
586 * -1, if drive detection failed
588 static int pt_probe(struct pt_unit
*tape
)
590 if (tape
->drive
== -1) {
591 for (tape
->drive
= 0; tape
->drive
<= 1; tape
->drive
++)
593 return pt_identify(tape
);
596 return pt_identify(tape
);
601 static int pt_detect(void)
603 struct pt_unit
*tape
;
604 int specified
= 0, found
= 0;
607 printk("%s: %s version %s, major %d\n", name
, name
, PT_VERSION
, major
);
609 par_drv
= pi_register_driver(name
);
611 pr_err("failed to register %s driver\n", name
);
616 for (unit
= 0; unit
< PT_UNITS
; unit
++) {
617 struct pt_unit
*tape
= &pt
[unit
];
618 tape
->pi
= &tape
->pia
;
619 atomic_set(&tape
->available
, 1);
621 tape
->last_sense
= 0;
624 tape
->drive
= DU
[D_SLV
];
625 snprintf(tape
->name
, PT_NAMELEN
, "%s%d", name
, unit
);
629 if (pi_init(tape
->pi
, 0, DU
[D_PRT
], DU
[D_MOD
], DU
[D_UNI
],
630 DU
[D_PRO
], DU
[D_DLY
], pt_scratch
, PI_PT
,
631 verbose
, tape
->name
)) {
632 if (!pt_probe(tape
)) {
636 pi_release(tape
->pi
);
639 if (specified
== 0) {
641 if (pi_init(tape
->pi
, 1, -1, -1, -1, -1, -1, pt_scratch
,
642 PI_PT
, verbose
, tape
->name
)) {
643 if (!pt_probe(tape
)) {
647 pi_release(tape
->pi
);
654 pi_unregister_driver(par_drv
);
655 printk("%s: No ATAPI tape drive detected\n", name
);
659 static int pt_open(struct inode
*inode
, struct file
*file
)
661 int unit
= iminor(inode
) & 0x7F;
662 struct pt_unit
*tape
= pt
+ unit
;
665 mutex_lock(&pt_mutex
);
666 if (unit
>= PT_UNITS
|| (!tape
->present
)) {
667 mutex_unlock(&pt_mutex
);
672 if (!atomic_dec_and_test(&tape
->available
))
678 if (!(tape
->flags
& PT_MEDIA
))
682 if ((!(tape
->flags
& PT_WRITE_OK
)) && (file
->f_mode
& FMODE_WRITE
))
685 if (!(iminor(inode
) & 128))
686 tape
->flags
|= PT_REWIND
;
689 tape
->bufptr
= kmalloc(PT_BUFSIZE
, GFP_KERNEL
);
690 if (tape
->bufptr
== NULL
) {
691 printk("%s: buffer allocation failed\n", tape
->name
);
695 file
->private_data
= tape
;
696 mutex_unlock(&pt_mutex
);
700 atomic_inc(&tape
->available
);
701 mutex_unlock(&pt_mutex
);
705 static long pt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
707 struct pt_unit
*tape
= file
->private_data
;
708 struct mtop __user
*p
= (void __user
*)arg
;
713 if (copy_from_user(&mtop
, p
, sizeof(struct mtop
)))
716 switch (mtop
.mt_op
) {
719 mutex_lock(&pt_mutex
);
721 mutex_unlock(&pt_mutex
);
725 mutex_lock(&pt_mutex
);
727 mutex_unlock(&pt_mutex
);
731 /* FIXME: rate limit ?? */
732 printk(KERN_DEBUG
"%s: Unimplemented mt_op %d\n", tape
->name
,
743 pt_release(struct inode
*inode
, struct file
*file
)
745 struct pt_unit
*tape
= file
->private_data
;
747 if (atomic_read(&tape
->available
) > 1)
750 if (tape
->flags
& PT_WRITING
)
753 if (tape
->flags
& PT_REWIND
)
759 atomic_inc(&tape
->available
);
765 static ssize_t
pt_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
* ppos
)
767 struct pt_unit
*tape
= filp
->private_data
;
768 struct pi_adapter
*pi
= tape
->pi
;
769 char rd_cmd
[12] = { ATAPI_READ_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
770 int k
, n
, r
, p
, s
, t
, b
;
772 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
773 tape
->flags
|= PT_READING
;
774 if (pt_atapi(tape
, rd_cmd
, 0, NULL
, "start read-ahead"))
776 } else if (tape
->flags
& PT_WRITING
)
779 if (tape
->flags
& PT_EOF
)
786 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "read"))
791 n
= 32768; /* max per command */
792 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
793 n
= b
* tape
->bs
; /* rounded up to even block */
797 r
= pt_command(tape
, rd_cmd
, n
, "read");
802 pt_req_sense(tape
, 0);
808 r
= pt_wait(tape
, STAT_BUSY
,
809 STAT_DRQ
| STAT_ERR
| STAT_READY
,
810 DBMSG("read DRQ"), "");
812 if (r
& STAT_SENSE
) {
814 pt_req_sense(tape
, 0);
819 tape
->flags
|= PT_EOF
;
826 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
827 p
= (read_reg(pi
, 2) & 3);
830 printk("%s: Phase error on read: %d\n", tape
->name
,
839 pi_read_block(pi
, tape
->bufptr
, k
);
844 if (copy_to_user(buf
+ t
, tape
->bufptr
, b
)) {
854 if (tape
->flags
& PT_EOF
)
862 static ssize_t
pt_write(struct file
*filp
, const char __user
*buf
, size_t count
, loff_t
* ppos
)
864 struct pt_unit
*tape
= filp
->private_data
;
865 struct pi_adapter
*pi
= tape
->pi
;
866 char wr_cmd
[12] = { ATAPI_WRITE_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
867 int k
, n
, r
, p
, s
, t
, b
;
869 if (!(tape
->flags
& PT_WRITE_OK
))
872 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
873 tape
->flags
|= PT_WRITING
;
875 (tape
, wr_cmd
, 0, NULL
, "start buffer-available mode"))
877 } else if (tape
->flags
& PT_READING
)
880 if (tape
->flags
& PT_EOF
)
887 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "write"))
892 n
= 32768; /* max per command */
893 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
894 n
= b
* tape
->bs
; /* rounded up to even block */
898 r
= pt_command(tape
, wr_cmd
, n
, "write");
902 if (r
) { /* error delivering command only */
903 pt_req_sense(tape
, 0);
909 r
= pt_wait(tape
, STAT_BUSY
,
910 STAT_DRQ
| STAT_ERR
| STAT_READY
,
911 DBMSG("write DRQ"), NULL
);
913 if (r
& STAT_SENSE
) {
915 pt_req_sense(tape
, 0);
920 tape
->flags
|= PT_EOF
;
927 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
928 p
= (read_reg(pi
, 2) & 3);
931 printk("%s: Phase error on write: %d \n",
943 if (copy_from_user(tape
->bufptr
, buf
+ t
, b
)) {
947 pi_write_block(pi
, tape
->bufptr
, k
);
955 if (tape
->flags
& PT_EOF
)
962 static int __init
pt_init(void)
977 err
= register_chrdev(major
, name
, &pt_fops
);
979 printk("pt_init: unable to get major number %d\n", major
);
980 for (unit
= 0; unit
< PT_UNITS
; unit
++)
981 if (pt
[unit
].present
)
982 pi_release(pt
[unit
].pi
);
986 pt_class
= class_create(THIS_MODULE
, "pt");
987 if (IS_ERR(pt_class
)) {
988 err
= PTR_ERR(pt_class
);
992 for (unit
= 0; unit
< PT_UNITS
; unit
++)
993 if (pt
[unit
].present
) {
994 device_create(pt_class
, NULL
, MKDEV(major
, unit
), NULL
,
996 device_create(pt_class
, NULL
, MKDEV(major
, unit
+ 128),
997 NULL
, "pt%dn", unit
);
1002 unregister_chrdev(major
, "pt");
1007 static void __exit
pt_exit(void)
1010 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1011 if (pt
[unit
].present
) {
1012 device_destroy(pt_class
, MKDEV(major
, unit
));
1013 device_destroy(pt_class
, MKDEV(major
, unit
+ 128));
1015 class_destroy(pt_class
);
1016 unregister_chrdev(major
, name
);
1017 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1018 if (pt
[unit
].present
)
1019 pi_release(pt
[unit
].pi
);
1022 MODULE_LICENSE("GPL");
1023 module_init(pt_init
)
1024 module_exit(pt_exit
)