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 /* Here are things one can override from the insmod command.
113 Most are autoprobed by paride unless set here. Verbose is on
118 static int verbose
= 0;
119 static int major
= PT_MAJOR
;
120 static char *name
= PT_NAME
;
121 static int disable
= 0;
123 static int drive0
[6] = { 0, 0, 0, -1, -1, -1 };
124 static int drive1
[6] = { 0, 0, 0, -1, -1, -1 };
125 static int drive2
[6] = { 0, 0, 0, -1, -1, -1 };
126 static int drive3
[6] = { 0, 0, 0, -1, -1, -1 };
128 static int (*drives
[4])[6] = {&drive0
, &drive1
, &drive2
, &drive3
};
137 #define DU (*drives[unit])
139 /* end of parameters */
141 #include <linux/module.h>
142 #include <linux/init.h>
143 #include <linux/fs.h>
144 #include <linux/delay.h>
145 #include <linux/slab.h>
146 #include <linux/mtio.h>
147 #include <linux/device.h>
148 #include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
149 #include <linux/mutex.h>
151 #include <asm/uaccess.h>
153 module_param(verbose
, bool, 0);
154 module_param(major
, int, 0);
155 module_param(name
, charp
, 0);
156 module_param_array(drive0
, int, NULL
, 0);
157 module_param_array(drive1
, int, NULL
, 0);
158 module_param_array(drive2
, int, NULL
, 0);
159 module_param_array(drive3
, int, NULL
, 0);
163 #define PT_MAX_RETRIES 5
164 #define PT_TMO 3000 /* interrupt timeout in jiffies */
165 #define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
166 #define PT_RESET_TMO 30 /* 30 seconds */
167 #define PT_READY_TMO 60 /* 60 seconds */
168 #define PT_REWIND_TMO 1200 /* 20 minutes */
170 #define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
172 #define STAT_ERR 0x00001
173 #define STAT_INDEX 0x00002
174 #define STAT_ECC 0x00004
175 #define STAT_DRQ 0x00008
176 #define STAT_SEEK 0x00010
177 #define STAT_WRERR 0x00020
178 #define STAT_READY 0x00040
179 #define STAT_BUSY 0x00080
180 #define STAT_SENSE 0x1f000
182 #define ATAPI_TEST_READY 0x00
183 #define ATAPI_REWIND 0x01
184 #define ATAPI_REQ_SENSE 0x03
185 #define ATAPI_READ_6 0x08
186 #define ATAPI_WRITE_6 0x0a
187 #define ATAPI_WFM 0x10
188 #define ATAPI_IDENTIFY 0x12
189 #define ATAPI_MODE_SENSE 0x1a
190 #define ATAPI_LOG_SENSE 0x4d
192 static DEFINE_MUTEX(pt_mutex
);
193 static int pt_open(struct inode
*inode
, struct file
*file
);
194 static long pt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
);
195 static int pt_release(struct inode
*inode
, struct file
*file
);
196 static ssize_t
pt_read(struct file
*filp
, char __user
*buf
,
197 size_t count
, loff_t
* ppos
);
198 static ssize_t
pt_write(struct file
*filp
, const char __user
*buf
,
199 size_t count
, loff_t
* ppos
);
200 static int pt_detect(void);
202 /* bits in tape->flags */
205 #define PT_WRITE_OK 2
208 #define PT_READING 16
212 #define PT_BUFSIZE 16384
215 struct pi_adapter pia
; /* interface to paride layer */
216 struct pi_adapter
*pi
;
217 int flags
; /* various state flags */
218 int last_sense
; /* result of last request sense */
219 int drive
; /* drive */
220 atomic_t available
; /* 1 if access is available 0 otherwise */
221 int bs
; /* block size */
222 int capacity
; /* Size of tape in KB */
223 int present
; /* device present ? */
225 char name
[PT_NAMELEN
]; /* pf0, pf1, ... */
228 static int pt_identify(struct pt_unit
*tape
);
230 static struct pt_unit pt
[PT_UNITS
];
232 static char pt_scratch
[512]; /* scratch block buffer */
234 /* kernel glue structures */
236 static const struct file_operations pt_fops
= {
237 .owner
= THIS_MODULE
,
240 .unlocked_ioctl
= pt_ioctl
,
242 .release
= pt_release
,
243 .llseek
= noop_llseek
,
246 /* sysfs class support */
247 static struct class *pt_class
;
249 static inline int status_reg(struct pi_adapter
*pi
)
251 return pi_read_regr(pi
, 1, 6);
254 static inline int read_reg(struct pi_adapter
*pi
, int reg
)
256 return pi_read_regr(pi
, 0, reg
);
259 static inline void write_reg(struct pi_adapter
*pi
, int reg
, int val
)
261 pi_write_regr(pi
, 0, reg
, val
);
264 static inline u8
DRIVE(struct pt_unit
*tape
)
266 return 0xa0+0x10*tape
->drive
;
269 static int pt_wait(struct pt_unit
*tape
, int go
, int stop
, char *fun
, char *msg
)
272 struct pi_adapter
*pi
= tape
->pi
;
275 while ((((r
= status_reg(pi
)) & go
) || (stop
&& (!(r
& stop
))))
279 if ((r
& (STAT_ERR
& stop
)) || (j
> PT_SPIN
)) {
286 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
287 " loop=%d phase=%d\n",
288 tape
->name
, fun
, msg
, r
, s
, e
, j
, p
);
294 static int pt_command(struct pt_unit
*tape
, char *cmd
, int dlen
, char *fun
)
296 struct pi_adapter
*pi
= tape
->pi
;
299 write_reg(pi
, 6, DRIVE(tape
));
301 if (pt_wait(tape
, STAT_BUSY
| STAT_DRQ
, 0, fun
, "before command")) {
306 write_reg(pi
, 4, dlen
% 256);
307 write_reg(pi
, 5, dlen
/ 256);
308 write_reg(pi
, 7, 0xa0); /* ATAPI packet command */
310 if (pt_wait(tape
, STAT_BUSY
, STAT_DRQ
, fun
, "command DRQ")) {
315 if (read_reg(pi
, 2) != 1) {
316 printk("%s: %s: command phase error\n", tape
->name
, fun
);
321 pi_write_block(pi
, cmd
, 12);
326 static int pt_completion(struct pt_unit
*tape
, char *buf
, char *fun
)
328 struct pi_adapter
*pi
= tape
->pi
;
331 r
= pt_wait(tape
, STAT_BUSY
, STAT_DRQ
| STAT_READY
| STAT_ERR
,
334 if (read_reg(pi
, 7) & STAT_DRQ
) {
335 n
= (((read_reg(pi
, 4) + 256 * read_reg(pi
, 5)) +
337 p
= read_reg(pi
, 2) & 3;
339 pi_write_block(pi
, buf
, n
);
341 pi_read_block(pi
, buf
, n
);
344 s
= pt_wait(tape
, STAT_BUSY
, STAT_READY
| STAT_ERR
, fun
, "data done");
351 static void pt_req_sense(struct pt_unit
*tape
, int quiet
)
353 char rs_cmd
[12] = { ATAPI_REQ_SENSE
, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
357 r
= pt_command(tape
, rs_cmd
, 16, "Request sense");
360 pt_completion(tape
, buf
, "Request sense");
362 tape
->last_sense
= -1;
365 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
366 tape
->name
, buf
[2] & 0xf, buf
[12], buf
[13]);
367 tape
->last_sense
= (buf
[2] & 0xf) | ((buf
[12] & 0xff) << 8)
368 | ((buf
[13] & 0xff) << 16);
372 static int pt_atapi(struct pt_unit
*tape
, char *cmd
, int dlen
, char *buf
, char *fun
)
376 r
= pt_command(tape
, cmd
, dlen
, fun
);
379 r
= pt_completion(tape
, buf
, fun
);
381 pt_req_sense(tape
, !fun
);
386 static void pt_sleep(int cs
)
388 schedule_timeout_interruptible(cs
);
391 static int pt_poll_dsc(struct pt_unit
*tape
, int pause
, int tmo
, char *msg
)
393 struct pi_adapter
*pi
= tape
->pi
;
403 write_reg(pi
, 6, DRIVE(tape
));
407 if (s
& (STAT_ERR
| STAT_SEEK
))
410 if ((k
>= tmo
) || (s
& STAT_ERR
)) {
412 printk("%s: %s DSC timeout\n", tape
->name
, msg
);
414 printk("%s: %s stat=0x%x err=0x%x\n", tape
->name
, msg
, s
,
416 pt_req_sense(tape
, 0);
422 static void pt_media_access_cmd(struct pt_unit
*tape
, int tmo
, char *cmd
, char *fun
)
424 if (pt_command(tape
, cmd
, 0, fun
)) {
425 pt_req_sense(tape
, 0);
428 pi_disconnect(tape
->pi
);
429 pt_poll_dsc(tape
, HZ
, tmo
, fun
);
432 static void pt_rewind(struct pt_unit
*tape
)
434 char rw_cmd
[12] = { ATAPI_REWIND
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
436 pt_media_access_cmd(tape
, PT_REWIND_TMO
, rw_cmd
, "rewind");
439 static void pt_write_fm(struct pt_unit
*tape
)
441 char wm_cmd
[12] = { ATAPI_WFM
, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
443 pt_media_access_cmd(tape
, PT_TMO
, wm_cmd
, "write filemark");
446 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
448 static int pt_reset(struct pt_unit
*tape
)
450 struct pi_adapter
*pi
= tape
->pi
;
452 int expect
[5] = { 1, 1, 1, 0x14, 0xeb };
455 write_reg(pi
, 6, DRIVE(tape
));
458 pt_sleep(20 * HZ
/ 1000);
461 while ((k
++ < PT_RESET_TMO
) && (status_reg(pi
) & STAT_BUSY
))
465 for (i
= 0; i
< 5; i
++)
466 flg
&= (read_reg(pi
, i
+ 1) == expect
[i
]);
469 printk("%s: Reset (%d) signature = ", tape
->name
, k
);
470 for (i
= 0; i
< 5; i
++)
471 printk("%3x", read_reg(pi
, i
+ 1));
473 printk(" (incorrect)");
481 static int pt_ready_wait(struct pt_unit
*tape
, int tmo
)
483 char tr_cmd
[12] = { ATAPI_TEST_READY
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
488 tape
->last_sense
= 0;
489 pt_atapi(tape
, tr_cmd
, 0, NULL
, DBMSG("test unit ready"));
490 p
= tape
->last_sense
;
493 if (!(((p
& 0xffff) == 0x0402) || ((p
& 0xff) == 6)))
498 return 0x000020; /* timeout */
501 static void xs(char *buf
, char *targ
, int offs
, int len
)
507 for (k
= 0; k
< len
; k
++)
508 if ((buf
[k
+ offs
] != 0x20) || (buf
[k
+ offs
] != l
))
509 l
= targ
[j
++] = buf
[k
+ offs
];
515 static int xn(char *buf
, int offs
, int size
)
520 for (k
= 0; k
< size
; k
++)
521 v
= v
* 256 + (buf
[k
+ offs
] & 0xff);
525 static int pt_identify(struct pt_unit
*tape
)
528 char *ms
[2] = { "master", "slave" };
530 char id_cmd
[12] = { ATAPI_IDENTIFY
, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
532 { ATAPI_MODE_SENSE
, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
534 { ATAPI_LOG_SENSE
, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
537 s
= pt_atapi(tape
, id_cmd
, 36, buf
, "identify");
544 printk("%s: Drive %d, unsupported type %d\n",
545 tape
->name
, tape
->drive
, dt
);
556 if (!pt_ready_wait(tape
, PT_READY_TMO
))
557 tape
->flags
|= PT_MEDIA
;
559 if (!pt_atapi(tape
, ms_cmd
, 36, buf
, "mode sense")) {
560 if (!(buf
[2] & 0x80))
561 tape
->flags
|= PT_WRITE_OK
;
562 tape
->bs
= xn(buf
, 10, 2);
565 if (!pt_atapi(tape
, ls_cmd
, 36, buf
, "log sense"))
566 tape
->capacity
= xn(buf
, 24, 4);
568 printk("%s: %s %s, %s", tape
->name
, mf
, id
, ms
[tape
->drive
]);
569 if (!(tape
->flags
& PT_MEDIA
))
570 printk(", no media\n");
572 if (!(tape
->flags
& PT_WRITE_OK
))
574 printk(", blocksize %d, %d MB\n", tape
->bs
, tape
->capacity
/ 1024);
582 * returns 0, with id set if drive is detected
583 * -1, if drive detection failed
585 static int pt_probe(struct pt_unit
*tape
)
587 if (tape
->drive
== -1) {
588 for (tape
->drive
= 0; tape
->drive
<= 1; tape
->drive
++)
590 return pt_identify(tape
);
593 return pt_identify(tape
);
598 static int pt_detect(void)
600 struct pt_unit
*tape
;
601 int specified
= 0, found
= 0;
604 printk("%s: %s version %s, major %d\n", name
, name
, PT_VERSION
, major
);
607 for (unit
= 0; unit
< PT_UNITS
; unit
++) {
608 struct pt_unit
*tape
= &pt
[unit
];
609 tape
->pi
= &tape
->pia
;
610 atomic_set(&tape
->available
, 1);
612 tape
->last_sense
= 0;
615 tape
->drive
= DU
[D_SLV
];
616 snprintf(tape
->name
, PT_NAMELEN
, "%s%d", name
, unit
);
620 if (pi_init(tape
->pi
, 0, DU
[D_PRT
], DU
[D_MOD
], DU
[D_UNI
],
621 DU
[D_PRO
], DU
[D_DLY
], pt_scratch
, PI_PT
,
622 verbose
, tape
->name
)) {
623 if (!pt_probe(tape
)) {
627 pi_release(tape
->pi
);
630 if (specified
== 0) {
632 if (pi_init(tape
->pi
, 1, -1, -1, -1, -1, -1, pt_scratch
,
633 PI_PT
, verbose
, tape
->name
)) {
634 if (!pt_probe(tape
)) {
638 pi_release(tape
->pi
);
645 printk("%s: No ATAPI tape drive detected\n", name
);
649 static int pt_open(struct inode
*inode
, struct file
*file
)
651 int unit
= iminor(inode
) & 0x7F;
652 struct pt_unit
*tape
= pt
+ unit
;
655 mutex_lock(&pt_mutex
);
656 if (unit
>= PT_UNITS
|| (!tape
->present
)) {
657 mutex_unlock(&pt_mutex
);
662 if (!atomic_dec_and_test(&tape
->available
))
668 if (!(tape
->flags
& PT_MEDIA
))
672 if ((!(tape
->flags
& PT_WRITE_OK
)) && (file
->f_mode
& FMODE_WRITE
))
675 if (!(iminor(inode
) & 128))
676 tape
->flags
|= PT_REWIND
;
679 tape
->bufptr
= kmalloc(PT_BUFSIZE
, GFP_KERNEL
);
680 if (tape
->bufptr
== NULL
) {
681 printk("%s: buffer allocation failed\n", tape
->name
);
685 file
->private_data
= tape
;
686 mutex_unlock(&pt_mutex
);
690 atomic_inc(&tape
->available
);
691 mutex_unlock(&pt_mutex
);
695 static long pt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
697 struct pt_unit
*tape
= file
->private_data
;
698 struct mtop __user
*p
= (void __user
*)arg
;
703 if (copy_from_user(&mtop
, p
, sizeof(struct mtop
)))
706 switch (mtop
.mt_op
) {
709 mutex_lock(&pt_mutex
);
711 mutex_unlock(&pt_mutex
);
715 mutex_lock(&pt_mutex
);
717 mutex_unlock(&pt_mutex
);
721 /* FIXME: rate limit ?? */
722 printk(KERN_DEBUG
"%s: Unimplemented mt_op %d\n", tape
->name
,
733 pt_release(struct inode
*inode
, struct file
*file
)
735 struct pt_unit
*tape
= file
->private_data
;
737 if (atomic_read(&tape
->available
) > 1)
740 if (tape
->flags
& PT_WRITING
)
743 if (tape
->flags
& PT_REWIND
)
749 atomic_inc(&tape
->available
);
755 static ssize_t
pt_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
* ppos
)
757 struct pt_unit
*tape
= filp
->private_data
;
758 struct pi_adapter
*pi
= tape
->pi
;
759 char rd_cmd
[12] = { ATAPI_READ_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
760 int k
, n
, r
, p
, s
, t
, b
;
762 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
763 tape
->flags
|= PT_READING
;
764 if (pt_atapi(tape
, rd_cmd
, 0, NULL
, "start read-ahead"))
766 } else if (tape
->flags
& PT_WRITING
)
769 if (tape
->flags
& PT_EOF
)
776 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "read"))
781 n
= 32768; /* max per command */
782 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
783 n
= b
* tape
->bs
; /* rounded up to even block */
787 r
= pt_command(tape
, rd_cmd
, n
, "read");
792 pt_req_sense(tape
, 0);
798 r
= pt_wait(tape
, STAT_BUSY
,
799 STAT_DRQ
| STAT_ERR
| STAT_READY
,
800 DBMSG("read DRQ"), "");
802 if (r
& STAT_SENSE
) {
804 pt_req_sense(tape
, 0);
809 tape
->flags
|= PT_EOF
;
816 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
817 p
= (read_reg(pi
, 2) & 3);
820 printk("%s: Phase error on read: %d\n", tape
->name
,
829 pi_read_block(pi
, tape
->bufptr
, k
);
834 if (copy_to_user(buf
+ t
, tape
->bufptr
, b
)) {
844 if (tape
->flags
& PT_EOF
)
852 static ssize_t
pt_write(struct file
*filp
, const char __user
*buf
, size_t count
, loff_t
* ppos
)
854 struct pt_unit
*tape
= filp
->private_data
;
855 struct pi_adapter
*pi
= tape
->pi
;
856 char wr_cmd
[12] = { ATAPI_WRITE_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
857 int k
, n
, r
, p
, s
, t
, b
;
859 if (!(tape
->flags
& PT_WRITE_OK
))
862 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
863 tape
->flags
|= PT_WRITING
;
865 (tape
, wr_cmd
, 0, NULL
, "start buffer-available mode"))
867 } else if (tape
->flags
& PT_READING
)
870 if (tape
->flags
& PT_EOF
)
877 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "write"))
882 n
= 32768; /* max per command */
883 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
884 n
= b
* tape
->bs
; /* rounded up to even block */
888 r
= pt_command(tape
, wr_cmd
, n
, "write");
892 if (r
) { /* error delivering command only */
893 pt_req_sense(tape
, 0);
899 r
= pt_wait(tape
, STAT_BUSY
,
900 STAT_DRQ
| STAT_ERR
| STAT_READY
,
901 DBMSG("write DRQ"), NULL
);
903 if (r
& STAT_SENSE
) {
905 pt_req_sense(tape
, 0);
910 tape
->flags
|= PT_EOF
;
917 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
918 p
= (read_reg(pi
, 2) & 3);
921 printk("%s: Phase error on write: %d \n",
933 if (copy_from_user(tape
->bufptr
, buf
+ t
, b
)) {
937 pi_write_block(pi
, tape
->bufptr
, k
);
945 if (tape
->flags
& PT_EOF
)
952 static int __init
pt_init(void)
967 err
= register_chrdev(major
, name
, &pt_fops
);
969 printk("pt_init: unable to get major number %d\n", major
);
970 for (unit
= 0; unit
< PT_UNITS
; unit
++)
971 if (pt
[unit
].present
)
972 pi_release(pt
[unit
].pi
);
976 pt_class
= class_create(THIS_MODULE
, "pt");
977 if (IS_ERR(pt_class
)) {
978 err
= PTR_ERR(pt_class
);
982 for (unit
= 0; unit
< PT_UNITS
; unit
++)
983 if (pt
[unit
].present
) {
984 device_create(pt_class
, NULL
, MKDEV(major
, unit
), NULL
,
986 device_create(pt_class
, NULL
, MKDEV(major
, unit
+ 128),
987 NULL
, "pt%dn", unit
);
992 unregister_chrdev(major
, "pt");
997 static void __exit
pt_exit(void)
1000 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1001 if (pt
[unit
].present
) {
1002 device_destroy(pt_class
, MKDEV(major
, unit
));
1003 device_destroy(pt_class
, MKDEV(major
, unit
+ 128));
1005 class_destroy(pt_class
);
1006 unregister_chrdev(major
, name
);
1007 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1008 if (pt
[unit
].present
)
1009 pi_release(pt
[unit
].pi
);
1012 MODULE_LICENSE("GPL");
1013 module_init(pt_init
)
1014 module_exit(pt_exit
)