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 bool 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 <asm/uaccess.h>
155 module_param(verbose
, bool, 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 */
236 /* kernel glue structures */
238 static const struct file_operations pt_fops
= {
239 .owner
= THIS_MODULE
,
242 .unlocked_ioctl
= pt_ioctl
,
244 .release
= pt_release
,
245 .llseek
= noop_llseek
,
248 /* sysfs class support */
249 static struct class *pt_class
;
251 static inline int status_reg(struct pi_adapter
*pi
)
253 return pi_read_regr(pi
, 1, 6);
256 static inline int read_reg(struct pi_adapter
*pi
, int reg
)
258 return pi_read_regr(pi
, 0, reg
);
261 static inline void write_reg(struct pi_adapter
*pi
, int reg
, int val
)
263 pi_write_regr(pi
, 0, reg
, val
);
266 static inline u8
DRIVE(struct pt_unit
*tape
)
268 return 0xa0+0x10*tape
->drive
;
271 static int pt_wait(struct pt_unit
*tape
, int go
, int stop
, char *fun
, char *msg
)
274 struct pi_adapter
*pi
= tape
->pi
;
277 while ((((r
= status_reg(pi
)) & go
) || (stop
&& (!(r
& stop
))))
281 if ((r
& (STAT_ERR
& stop
)) || (j
> PT_SPIN
)) {
288 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
289 " loop=%d phase=%d\n",
290 tape
->name
, fun
, msg
, r
, s
, e
, j
, p
);
296 static int pt_command(struct pt_unit
*tape
, char *cmd
, int dlen
, char *fun
)
298 struct pi_adapter
*pi
= tape
->pi
;
301 write_reg(pi
, 6, DRIVE(tape
));
303 if (pt_wait(tape
, STAT_BUSY
| STAT_DRQ
, 0, fun
, "before command")) {
308 write_reg(pi
, 4, dlen
% 256);
309 write_reg(pi
, 5, dlen
/ 256);
310 write_reg(pi
, 7, 0xa0); /* ATAPI packet command */
312 if (pt_wait(tape
, STAT_BUSY
, STAT_DRQ
, fun
, "command DRQ")) {
317 if (read_reg(pi
, 2) != 1) {
318 printk("%s: %s: command phase error\n", tape
->name
, fun
);
323 pi_write_block(pi
, cmd
, 12);
328 static int pt_completion(struct pt_unit
*tape
, char *buf
, char *fun
)
330 struct pi_adapter
*pi
= tape
->pi
;
333 r
= pt_wait(tape
, STAT_BUSY
, STAT_DRQ
| STAT_READY
| STAT_ERR
,
336 if (read_reg(pi
, 7) & STAT_DRQ
) {
337 n
= (((read_reg(pi
, 4) + 256 * read_reg(pi
, 5)) +
339 p
= read_reg(pi
, 2) & 3;
341 pi_write_block(pi
, buf
, n
);
343 pi_read_block(pi
, buf
, n
);
346 s
= pt_wait(tape
, STAT_BUSY
, STAT_READY
| STAT_ERR
, fun
, "data done");
353 static void pt_req_sense(struct pt_unit
*tape
, int quiet
)
355 char rs_cmd
[12] = { ATAPI_REQ_SENSE
, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
359 r
= pt_command(tape
, rs_cmd
, 16, "Request sense");
362 pt_completion(tape
, buf
, "Request sense");
364 tape
->last_sense
= -1;
367 printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
368 tape
->name
, buf
[2] & 0xf, buf
[12], buf
[13]);
369 tape
->last_sense
= (buf
[2] & 0xf) | ((buf
[12] & 0xff) << 8)
370 | ((buf
[13] & 0xff) << 16);
374 static int pt_atapi(struct pt_unit
*tape
, char *cmd
, int dlen
, char *buf
, char *fun
)
378 r
= pt_command(tape
, cmd
, dlen
, fun
);
381 r
= pt_completion(tape
, buf
, fun
);
383 pt_req_sense(tape
, !fun
);
388 static void pt_sleep(int cs
)
390 schedule_timeout_interruptible(cs
);
393 static int pt_poll_dsc(struct pt_unit
*tape
, int pause
, int tmo
, char *msg
)
395 struct pi_adapter
*pi
= tape
->pi
;
405 write_reg(pi
, 6, DRIVE(tape
));
409 if (s
& (STAT_ERR
| STAT_SEEK
))
412 if ((k
>= tmo
) || (s
& STAT_ERR
)) {
414 printk("%s: %s DSC timeout\n", tape
->name
, msg
);
416 printk("%s: %s stat=0x%x err=0x%x\n", tape
->name
, msg
, s
,
418 pt_req_sense(tape
, 0);
424 static void pt_media_access_cmd(struct pt_unit
*tape
, int tmo
, char *cmd
, char *fun
)
426 if (pt_command(tape
, cmd
, 0, fun
)) {
427 pt_req_sense(tape
, 0);
430 pi_disconnect(tape
->pi
);
431 pt_poll_dsc(tape
, HZ
, tmo
, fun
);
434 static void pt_rewind(struct pt_unit
*tape
)
436 char rw_cmd
[12] = { ATAPI_REWIND
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
438 pt_media_access_cmd(tape
, PT_REWIND_TMO
, rw_cmd
, "rewind");
441 static void pt_write_fm(struct pt_unit
*tape
)
443 char wm_cmd
[12] = { ATAPI_WFM
, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
445 pt_media_access_cmd(tape
, PT_TMO
, wm_cmd
, "write filemark");
448 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
450 static int pt_reset(struct pt_unit
*tape
)
452 struct pi_adapter
*pi
= tape
->pi
;
454 int expect
[5] = { 1, 1, 1, 0x14, 0xeb };
457 write_reg(pi
, 6, DRIVE(tape
));
460 pt_sleep(20 * HZ
/ 1000);
463 while ((k
++ < PT_RESET_TMO
) && (status_reg(pi
) & STAT_BUSY
))
467 for (i
= 0; i
< 5; i
++)
468 flg
&= (read_reg(pi
, i
+ 1) == expect
[i
]);
471 printk("%s: Reset (%d) signature = ", tape
->name
, k
);
472 for (i
= 0; i
< 5; i
++)
473 printk("%3x", read_reg(pi
, i
+ 1));
475 printk(" (incorrect)");
483 static int pt_ready_wait(struct pt_unit
*tape
, int tmo
)
485 char tr_cmd
[12] = { ATAPI_TEST_READY
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
490 tape
->last_sense
= 0;
491 pt_atapi(tape
, tr_cmd
, 0, NULL
, DBMSG("test unit ready"));
492 p
= tape
->last_sense
;
495 if (!(((p
& 0xffff) == 0x0402) || ((p
& 0xff) == 6)))
500 return 0x000020; /* timeout */
503 static void xs(char *buf
, char *targ
, int offs
, int len
)
509 for (k
= 0; k
< len
; k
++)
510 if ((buf
[k
+ offs
] != 0x20) || (buf
[k
+ offs
] != l
))
511 l
= targ
[j
++] = buf
[k
+ offs
];
517 static int xn(char *buf
, int offs
, int size
)
522 for (k
= 0; k
< size
; k
++)
523 v
= v
* 256 + (buf
[k
+ offs
] & 0xff);
527 static int pt_identify(struct pt_unit
*tape
)
530 char *ms
[2] = { "master", "slave" };
532 char id_cmd
[12] = { ATAPI_IDENTIFY
, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
534 { ATAPI_MODE_SENSE
, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
536 { ATAPI_LOG_SENSE
, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
539 s
= pt_atapi(tape
, id_cmd
, 36, buf
, "identify");
546 printk("%s: Drive %d, unsupported type %d\n",
547 tape
->name
, tape
->drive
, dt
);
558 if (!pt_ready_wait(tape
, PT_READY_TMO
))
559 tape
->flags
|= PT_MEDIA
;
561 if (!pt_atapi(tape
, ms_cmd
, 36, buf
, "mode sense")) {
562 if (!(buf
[2] & 0x80))
563 tape
->flags
|= PT_WRITE_OK
;
564 tape
->bs
= xn(buf
, 10, 2);
567 if (!pt_atapi(tape
, ls_cmd
, 36, buf
, "log sense"))
568 tape
->capacity
= xn(buf
, 24, 4);
570 printk("%s: %s %s, %s", tape
->name
, mf
, id
, ms
[tape
->drive
]);
571 if (!(tape
->flags
& PT_MEDIA
))
572 printk(", no media\n");
574 if (!(tape
->flags
& PT_WRITE_OK
))
576 printk(", blocksize %d, %d MB\n", tape
->bs
, tape
->capacity
/ 1024);
584 * returns 0, with id set if drive is detected
585 * -1, if drive detection failed
587 static int pt_probe(struct pt_unit
*tape
)
589 if (tape
->drive
== -1) {
590 for (tape
->drive
= 0; tape
->drive
<= 1; tape
->drive
++)
592 return pt_identify(tape
);
595 return pt_identify(tape
);
600 static int pt_detect(void)
602 struct pt_unit
*tape
;
603 int specified
= 0, found
= 0;
606 printk("%s: %s version %s, major %d\n", name
, name
, PT_VERSION
, major
);
609 for (unit
= 0; unit
< PT_UNITS
; unit
++) {
610 struct pt_unit
*tape
= &pt
[unit
];
611 tape
->pi
= &tape
->pia
;
612 atomic_set(&tape
->available
, 1);
614 tape
->last_sense
= 0;
617 tape
->drive
= DU
[D_SLV
];
618 snprintf(tape
->name
, PT_NAMELEN
, "%s%d", name
, unit
);
622 if (pi_init(tape
->pi
, 0, DU
[D_PRT
], DU
[D_MOD
], DU
[D_UNI
],
623 DU
[D_PRO
], DU
[D_DLY
], pt_scratch
, PI_PT
,
624 verbose
, tape
->name
)) {
625 if (!pt_probe(tape
)) {
629 pi_release(tape
->pi
);
632 if (specified
== 0) {
634 if (pi_init(tape
->pi
, 1, -1, -1, -1, -1, -1, pt_scratch
,
635 PI_PT
, verbose
, tape
->name
)) {
636 if (!pt_probe(tape
)) {
640 pi_release(tape
->pi
);
647 printk("%s: No ATAPI tape drive detected\n", name
);
651 static int pt_open(struct inode
*inode
, struct file
*file
)
653 int unit
= iminor(inode
) & 0x7F;
654 struct pt_unit
*tape
= pt
+ unit
;
657 mutex_lock(&pt_mutex
);
658 if (unit
>= PT_UNITS
|| (!tape
->present
)) {
659 mutex_unlock(&pt_mutex
);
664 if (!atomic_dec_and_test(&tape
->available
))
670 if (!(tape
->flags
& PT_MEDIA
))
674 if ((!(tape
->flags
& PT_WRITE_OK
)) && (file
->f_mode
& FMODE_WRITE
))
677 if (!(iminor(inode
) & 128))
678 tape
->flags
|= PT_REWIND
;
681 tape
->bufptr
= kmalloc(PT_BUFSIZE
, GFP_KERNEL
);
682 if (tape
->bufptr
== NULL
) {
683 printk("%s: buffer allocation failed\n", tape
->name
);
687 file
->private_data
= tape
;
688 mutex_unlock(&pt_mutex
);
692 atomic_inc(&tape
->available
);
693 mutex_unlock(&pt_mutex
);
697 static long pt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
699 struct pt_unit
*tape
= file
->private_data
;
700 struct mtop __user
*p
= (void __user
*)arg
;
705 if (copy_from_user(&mtop
, p
, sizeof(struct mtop
)))
708 switch (mtop
.mt_op
) {
711 mutex_lock(&pt_mutex
);
713 mutex_unlock(&pt_mutex
);
717 mutex_lock(&pt_mutex
);
719 mutex_unlock(&pt_mutex
);
723 /* FIXME: rate limit ?? */
724 printk(KERN_DEBUG
"%s: Unimplemented mt_op %d\n", tape
->name
,
735 pt_release(struct inode
*inode
, struct file
*file
)
737 struct pt_unit
*tape
= file
->private_data
;
739 if (atomic_read(&tape
->available
) > 1)
742 if (tape
->flags
& PT_WRITING
)
745 if (tape
->flags
& PT_REWIND
)
751 atomic_inc(&tape
->available
);
757 static ssize_t
pt_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
* ppos
)
759 struct pt_unit
*tape
= filp
->private_data
;
760 struct pi_adapter
*pi
= tape
->pi
;
761 char rd_cmd
[12] = { ATAPI_READ_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
762 int k
, n
, r
, p
, s
, t
, b
;
764 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
765 tape
->flags
|= PT_READING
;
766 if (pt_atapi(tape
, rd_cmd
, 0, NULL
, "start read-ahead"))
768 } else if (tape
->flags
& PT_WRITING
)
771 if (tape
->flags
& PT_EOF
)
778 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "read"))
783 n
= 32768; /* max per command */
784 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
785 n
= b
* tape
->bs
; /* rounded up to even block */
789 r
= pt_command(tape
, rd_cmd
, n
, "read");
794 pt_req_sense(tape
, 0);
800 r
= pt_wait(tape
, STAT_BUSY
,
801 STAT_DRQ
| STAT_ERR
| STAT_READY
,
802 DBMSG("read DRQ"), "");
804 if (r
& STAT_SENSE
) {
806 pt_req_sense(tape
, 0);
811 tape
->flags
|= PT_EOF
;
818 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
819 p
= (read_reg(pi
, 2) & 3);
822 printk("%s: Phase error on read: %d\n", tape
->name
,
831 pi_read_block(pi
, tape
->bufptr
, k
);
836 if (copy_to_user(buf
+ t
, tape
->bufptr
, b
)) {
846 if (tape
->flags
& PT_EOF
)
854 static ssize_t
pt_write(struct file
*filp
, const char __user
*buf
, size_t count
, loff_t
* ppos
)
856 struct pt_unit
*tape
= filp
->private_data
;
857 struct pi_adapter
*pi
= tape
->pi
;
858 char wr_cmd
[12] = { ATAPI_WRITE_6
, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
859 int k
, n
, r
, p
, s
, t
, b
;
861 if (!(tape
->flags
& PT_WRITE_OK
))
864 if (!(tape
->flags
& (PT_READING
| PT_WRITING
))) {
865 tape
->flags
|= PT_WRITING
;
867 (tape
, wr_cmd
, 0, NULL
, "start buffer-available mode"))
869 } else if (tape
->flags
& PT_READING
)
872 if (tape
->flags
& PT_EOF
)
879 if (!pt_poll_dsc(tape
, HZ
/ 100, PT_TMO
, "write"))
884 n
= 32768; /* max per command */
885 b
= (n
- 1 + tape
->bs
) / tape
->bs
;
886 n
= b
* tape
->bs
; /* rounded up to even block */
890 r
= pt_command(tape
, wr_cmd
, n
, "write");
894 if (r
) { /* error delivering command only */
895 pt_req_sense(tape
, 0);
901 r
= pt_wait(tape
, STAT_BUSY
,
902 STAT_DRQ
| STAT_ERR
| STAT_READY
,
903 DBMSG("write DRQ"), NULL
);
905 if (r
& STAT_SENSE
) {
907 pt_req_sense(tape
, 0);
912 tape
->flags
|= PT_EOF
;
919 n
= (read_reg(pi
, 4) + 256 * read_reg(pi
, 5));
920 p
= (read_reg(pi
, 2) & 3);
923 printk("%s: Phase error on write: %d \n",
935 if (copy_from_user(tape
->bufptr
, buf
+ t
, b
)) {
939 pi_write_block(pi
, tape
->bufptr
, k
);
947 if (tape
->flags
& PT_EOF
)
954 static int __init
pt_init(void)
969 err
= register_chrdev(major
, name
, &pt_fops
);
971 printk("pt_init: unable to get major number %d\n", major
);
972 for (unit
= 0; unit
< PT_UNITS
; unit
++)
973 if (pt
[unit
].present
)
974 pi_release(pt
[unit
].pi
);
978 pt_class
= class_create(THIS_MODULE
, "pt");
979 if (IS_ERR(pt_class
)) {
980 err
= PTR_ERR(pt_class
);
984 for (unit
= 0; unit
< PT_UNITS
; unit
++)
985 if (pt
[unit
].present
) {
986 device_create(pt_class
, NULL
, MKDEV(major
, unit
), NULL
,
988 device_create(pt_class
, NULL
, MKDEV(major
, unit
+ 128),
989 NULL
, "pt%dn", unit
);
994 unregister_chrdev(major
, "pt");
999 static void __exit
pt_exit(void)
1002 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1003 if (pt
[unit
].present
) {
1004 device_destroy(pt_class
, MKDEV(major
, unit
));
1005 device_destroy(pt_class
, MKDEV(major
, unit
+ 128));
1007 class_destroy(pt_class
);
1008 unregister_chrdev(major
, name
);
1009 for (unit
= 0; unit
< PT_UNITS
; unit
++)
1010 if (pt
[unit
].present
)
1011 pi_release(pt
[unit
].pi
);
1014 MODULE_LICENSE("GPL");
1015 module_init(pt_init
)
1016 module_exit(pt_exit
)