Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
93e0e677
Commit
93e0e677
authored
May 24, 2003
by
Alexander Viro
Committed by
Linus Torvalds
May 24, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] pt.c Lindent
pt.c fed through Lindent
parent
46530a99
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
545 additions
and
478 deletions
+545
-478
drivers/block/paride/pt.c
drivers/block/paride/pt.c
+545
-478
No files found.
drivers/block/paride/pt.c
View file @
93e0e677
...
@@ -115,17 +115,17 @@
...
@@ -115,17 +115,17 @@
*/
*/
static
int
verbose
=
0
;
static
int
verbose
=
0
;
static
int
major
=
PT_MAJOR
;
static
int
major
=
PT_MAJOR
;
static
char
*
name
=
PT_NAME
;
static
char
*
name
=
PT_NAME
;
static
int
disable
=
0
;
static
int
disable
=
0
;
static
int
drive0
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive0
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive1
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive1
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive2
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive2
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive3
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
drive3
[
6
]
=
{
0
,
0
,
0
,
-
1
,
-
1
,
-
1
};
static
int
(
*
drives
[
4
])[
6
]
=
{
&
drive0
,
&
drive1
,
&
drive2
,
&
drive3
};
static
int
(
*
drives
[
4
])[
6
]
=
{
&
drive0
,
&
drive1
,
&
drive2
,
&
drive3
};
static
int
pt_drive_count
;
static
int
pt_drive_count
;
#define D_PRT 0
#define D_PRT 0
...
@@ -139,7 +139,6 @@ static int pt_drive_count;
...
@@ -139,7 +139,6 @@ static int pt_drive_count;
/* end of parameters */
/* end of parameters */
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/fs.h>
...
@@ -154,37 +153,40 @@ static int pt_drive_count;
...
@@ -154,37 +153,40 @@ static int pt_drive_count;
#include "setup.h"
#include "setup.h"
static
STT
pt_stt
[
5
]
=
{
{
"drive0"
,
6
,
drive0
},
static
STT
pt_stt
[
5
]
=
{
{
"drive1"
,
6
,
drive1
},
{
"drive0"
,
6
,
drive0
},
{
"drive2"
,
6
,
drive2
},
{
"drive1"
,
6
,
drive1
},
{
"drive3"
,
6
,
drive3
},
{
"drive2"
,
6
,
drive2
},
{
"disable"
,
1
,
&
disable
}};
{
"drive3"
,
6
,
drive3
},
{
"disable"
,
1
,
&
disable
}
void
pt_setup
(
char
*
str
,
int
*
ints
)
};
{
generic_setup
(
pt_stt
,
5
,
str
);
void
pt_setup
(
char
*
str
,
int
*
ints
)
{
generic_setup
(
pt_stt
,
5
,
str
);
}
}
#endif
#endif
MODULE_PARM
(
verbose
,
"i"
);
MODULE_PARM
(
verbose
,
"i"
);
MODULE_PARM
(
major
,
"i"
);
MODULE_PARM
(
major
,
"i"
);
MODULE_PARM
(
name
,
"s"
);
MODULE_PARM
(
name
,
"s"
);
MODULE_PARM
(
drive0
,
"1-6i"
);
MODULE_PARM
(
drive0
,
"1-6i"
);
MODULE_PARM
(
drive1
,
"1-6i"
);
MODULE_PARM
(
drive1
,
"1-6i"
);
MODULE_PARM
(
drive2
,
"1-6i"
);
MODULE_PARM
(
drive2
,
"1-6i"
);
MODULE_PARM
(
drive3
,
"1-6i"
);
MODULE_PARM
(
drive3
,
"1-6i"
);
#include "paride.h"
#include "paride.h"
#define PT_MAX_RETRIES 5
#define PT_MAX_RETRIES 5
#define PT_TMO 3000
/* interrupt timeout in jiffies */
#define PT_TMO 3000
/* interrupt timeout in jiffies */
#define PT_SPIN_DEL 50
/* spin delay in micro-seconds */
#define PT_SPIN_DEL 50
/* spin delay in micro-seconds */
#define PT_RESET_TMO 30
/* 30 seconds */
#define PT_RESET_TMO 30
/* 30 seconds */
#define PT_READY_TMO 60
/* 60 seconds */
#define PT_READY_TMO 60
/* 60 seconds */
#define PT_REWIND_TMO 1200
/* 20 minutes */
#define PT_REWIND_TMO 1200
/* 20 minutes */
#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
#define STAT_ERR 0x00001
#define STAT_ERR 0x00001
#define STAT_INDEX 0x00002
#define STAT_INDEX 0x00002
...
@@ -207,16 +209,16 @@ MODULE_PARM(drive3,"1-6i");
...
@@ -207,16 +209,16 @@ MODULE_PARM(drive3,"1-6i");
#define ATAPI_LOG_SENSE 0x4d
#define ATAPI_LOG_SENSE 0x4d
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
size_t
count
,
loff_t
*
ppos
);
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
size_t
count
,
loff_t
*
ppos
);
static
int
pt_detect
(
void
);
static
int
pt_detect
(
void
);
static
int
pt_identify
(
int
unit
);
static
int
pt_identify
(
int
unit
);
/* bits in PT.flags */
/* bits in PT.flags */
...
@@ -231,18 +233,18 @@ static int pt_identify (int unit);
...
@@ -231,18 +233,18 @@ static int pt_identify (int unit);
#define PT_BUFSIZE 16384
#define PT_BUFSIZE 16384
struct
pt_unit
{
struct
pt_unit
{
struct
pi_adapter
pia
;
/* interface to paride layer */
struct
pi_adapter
pia
;
/* interface to paride layer */
struct
pi_adapter
*
pi
;
struct
pi_adapter
*
pi
;
int
flags
;
/* various state flags */
int
flags
;
/* various state flags */
int
last_sense
;
/* result of last request sense */
int
last_sense
;
/* result of last request sense */
int
drive
;
/* drive */
int
drive
;
/* drive */
atomic_t
available
;
/* 1 if access is available 0 otherwise */
atomic_t
available
;
/* 1 if access is available 0 otherwise */
int
bs
;
/* block size */
int
bs
;
/* block size */
int
capacity
;
/* Size of tape in KB */
int
capacity
;
/* Size of tape in KB */
int
present
;
/* device present ? */
int
present
;
/* device present ? */
char
*
bufptr
;
char
*
bufptr
;
char
name
[
PT_NAMELEN
];
/* pf0, pf1, ... */
char
name
[
PT_NAMELEN
];
/* pf0, pf1, ... */
};
};
struct
pt_unit
pt
[
PT_UNITS
];
struct
pt_unit
pt
[
PT_UNITS
];
...
@@ -251,38 +253,40 @@ struct pt_unit pt[PT_UNITS];
...
@@ -251,38 +253,40 @@ struct pt_unit pt[PT_UNITS];
#define PT pt[unit]
#define PT pt[unit]
#define PI PT.pi
#define PI PT.pi
static
char
pt_scratch
[
512
];
/* scratch block buffer */
static
char
pt_scratch
[
512
];
/* scratch block buffer */
/* kernel glue structures */
/* kernel glue structures */
static
struct
file_operations
pt_fops
=
{
static
struct
file_operations
pt_fops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
read
=
pt_read
,
.
read
=
pt_read
,
.
write
=
pt_write
,
.
write
=
pt_write
,
.
ioctl
=
pt_ioctl
,
.
ioctl
=
pt_ioctl
,
.
open
=
pt_open
,
.
open
=
pt_open
,
.
release
=
pt_release
,
.
release
=
pt_release
,
};
};
void
pt_init_units
(
void
)
static
void
pt_init_units
(
void
)
{
{
int
unit
,
j
;
int
unit
,
j
;
pt_drive_count
=
0
;
pt_drive_count
=
0
;
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
{
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
{
PT
.
pi
=
&
PT
.
pia
;
PT
.
pi
=
&
PT
.
pia
;
atomic_set
(
&
PT
.
available
,
1
);
atomic_set
(
&
PT
.
available
,
1
);
PT
.
flags
=
0
;
PT
.
flags
=
0
;
PT
.
last_sense
=
0
;
PT
.
last_sense
=
0
;
PT
.
present
=
0
;
PT
.
present
=
0
;
PT
.
bufptr
=
NULL
;
PT
.
bufptr
=
NULL
;
PT
.
drive
=
DU
[
D_SLV
];
PT
.
drive
=
DU
[
D_SLV
];
j
=
0
;
j
=
0
;
while
((
j
<
PT_NAMELEN
-
2
)
&&
(
PT
.
name
[
j
]
=
name
[
j
]))
j
++
;
while
((
j
<
PT_NAMELEN
-
2
)
&&
(
PT
.
name
[
j
]
=
name
[
j
]))
PT
.
name
[
j
++
]
=
'0'
+
unit
;
j
++
;
PT
.
name
[
j
]
=
0
;
PT
.
name
[
j
++
]
=
'0'
+
unit
;
if
(
DU
[
D_PRT
])
pt_drive_count
++
;
PT
.
name
[
j
]
=
0
;
}
if
(
DU
[
D_PRT
])
pt_drive_count
++
;
}
}
}
static
inline
int
status_reg
(
int
unit
)
static
inline
int
status_reg
(
int
unit
)
...
@@ -302,602 +306,665 @@ static inline void write_reg(int unit, int reg, int val)
...
@@ -302,602 +306,665 @@ static inline void write_reg(int unit, int reg, int val)
#define DRIVE (0xa0+0x10*PT.drive)
#define DRIVE (0xa0+0x10*PT.drive)
static
int
pt_wait
(
int
unit
,
int
go
,
int
stop
,
char
*
fun
,
char
*
msg
)
static
int
pt_wait
(
int
unit
,
int
go
,
int
stop
,
char
*
fun
,
char
*
msg
)
{
{
int
j
,
r
,
e
,
s
,
p
;
int
j
,
r
,
e
,
s
,
p
;
j
=
0
;
while
((((
r
=
status_reg
(
unit
))
&
go
)
||
(
stop
&&
(
!
(
r
&
stop
))))
&&
(
j
++<
PT_SPIN
))
udelay
(
PT_SPIN_DEL
);
if
((
r
&
(
STAT_ERR
&
stop
))
||
(
j
>=
PT_SPIN
))
{
s
=
read_reg
(
unit
,
7
);
e
=
read_reg
(
unit
,
1
);
p
=
read_reg
(
unit
,
2
);
if
(
j
>=
PT_SPIN
)
e
|=
0x100
;
if
(
fun
)
printk
(
"%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
" loop=%d phase=%d
\n
"
,
PT
.
name
,
fun
,
msg
,
r
,
s
,
e
,
j
,
p
);
return
(
e
<<
8
)
+
s
;
}
return
0
;
}
static
int
pt_command
(
int
unit
,
char
*
cmd
,
int
dlen
,
char
*
fun
)
{
pi_connect
(
PI
);
write_reg
(
unit
,
6
,
DRIVE
);
j
=
0
;
while
((((
r
=
status_reg
(
unit
))
&
go
)
||
(
stop
&&
(
!
(
r
&
stop
))))
&&
(
j
++
<
PT_SPIN
))
udelay
(
PT_SPIN_DEL
);
if
(
pt_wait
(
unit
,
STAT_BUSY
|
STAT_DRQ
,
0
,
fun
,
"before command"
))
{
if
((
r
&
(
STAT_ERR
&
stop
))
||
(
j
>=
PT_SPIN
))
{
pi_disconnect
(
PI
);
s
=
read_reg
(
unit
,
7
);
return
-
1
;
e
=
read_reg
(
unit
,
1
);
}
p
=
read_reg
(
unit
,
2
);
if
(
j
>=
PT_SPIN
)
e
|=
0x100
;
if
(
fun
)
printk
(
"%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
" loop=%d phase=%d
\n
"
,
PT
.
name
,
fun
,
msg
,
r
,
s
,
e
,
j
,
p
);
return
(
e
<<
8
)
+
s
;
}
return
0
;
}
write_reg
(
unit
,
4
,
dlen
%
256
);
static
int
pt_command
(
int
unit
,
char
*
cmd
,
int
dlen
,
char
*
fun
)
write_reg
(
unit
,
5
,
dlen
/
256
);
{
write_reg
(
unit
,
7
,
0xa0
);
/* ATAPI packet command */
pi_connect
(
PI
);
if
(
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
,
fun
,
"command DRQ"
))
{
write_reg
(
unit
,
6
,
DRIVE
);
pi_disconnect
(
PI
);
return
-
1
;
}
if
(
read_reg
(
unit
,
2
)
!=
1
)
{
if
(
pt_wait
(
unit
,
STAT_BUSY
|
STAT_DRQ
,
0
,
fun
,
"before command"
))
{
printk
(
"%s: %s: command phase error
\n
"
,
PT
.
name
,
fun
);
pi_disconnect
(
PI
);
pi_disconnect
(
PI
);
return
-
1
;
return
-
1
;
}
}
pi_write_block
(
PI
,
cmd
,
12
);
write_reg
(
unit
,
4
,
dlen
%
256
);
write_reg
(
unit
,
5
,
dlen
/
256
);
write_reg
(
unit
,
7
,
0xa0
);
/* ATAPI packet command */
return
0
;
if
(
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
,
fun
,
"command DRQ"
))
{
}
pi_disconnect
(
PI
);
return
-
1
;
}
static
int
pt_completion
(
int
unit
,
char
*
buf
,
char
*
fun
)
if
(
read_reg
(
unit
,
2
)
!=
1
)
{
printk
(
"%s: %s: command phase error
\n
"
,
PT
.
name
,
fun
);
pi_disconnect
(
PI
);
return
-
1
;
}
{
int
r
,
s
,
n
,
p
;
pi_write_block
(
PI
,
cmd
,
12
)
;
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_READY
|
STAT_ERR
,
return
0
;
fun
,
"completion"
);
}
if
(
read_reg
(
unit
,
7
)
&
STAT_DRQ
)
{
static
int
pt_completion
(
int
unit
,
char
*
buf
,
char
*
fun
)
n
=
(((
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
))
+
3
)
&
0xfffc
);
{
p
=
read_reg
(
unit
,
2
)
&
3
;
int
r
,
s
,
n
,
p
;
if
(
p
==
0
)
pi_write_block
(
PI
,
buf
,
n
);
if
(
p
==
2
)
pi_read_block
(
PI
,
buf
,
n
);
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_READY
|
STAT_ERR
,
}
fun
,
"completion"
);
if
(
read_reg
(
unit
,
7
)
&
STAT_DRQ
)
{
n
=
(((
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
))
+
3
)
&
0xfffc
);
p
=
read_reg
(
unit
,
2
)
&
3
;
if
(
p
==
0
)
pi_write_block
(
PI
,
buf
,
n
);
if
(
p
==
2
)
pi_read_block
(
PI
,
buf
,
n
);
}
s
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_READY
|
STAT_ERR
,
fun
,
"data done"
);
s
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_READY
|
STAT_ERR
,
fun
,
"data done"
);
pi_disconnect
(
PI
);
pi_disconnect
(
PI
);
return
(
r
?
r
:
s
);
return
(
r
?
r
:
s
);
}
}
static
void
pt_req_sense
(
int
unit
,
int
quiet
)
static
void
pt_req_sense
(
int
unit
,
int
quiet
)
{
{
char
rs_cmd
[
12
]
=
{
ATAPI_REQ_SENSE
,
0
,
0
,
0
,
16
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
rs_cmd
[
12
]
=
{
ATAPI_REQ_SENSE
,
0
,
0
,
0
,
16
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
buf
[
16
];
char
buf
[
16
];
int
r
;
int
r
;
r
=
pt_command
(
unit
,
rs_cmd
,
16
,
"Request sense"
);
r
=
pt_command
(
unit
,
rs_cmd
,
16
,
"Request sense"
);
mdelay
(
1
);
mdelay
(
1
);
if
(
!
r
)
pt_completion
(
unit
,
buf
,
"Request sense"
);
if
(
!
r
)
pt_completion
(
unit
,
buf
,
"Request sense"
);
PT
.
last_sense
=
-
1
;
PT
.
last_sense
=
-
1
;
if
(
!
r
)
{
if
(
!
r
)
{
if
(
!
quiet
)
printk
(
"%s: Sense key: %x, ASC: %x, ASQ: %x
\n
"
,
if
(
!
quiet
)
PT
.
name
,
buf
[
2
]
&
0xf
,
buf
[
12
],
buf
[
13
]);
printk
(
"%s: Sense key: %x, ASC: %x, ASQ: %x
\n
"
,
PT
.
last_sense
=
(
buf
[
2
]
&
0xf
)
|
((
buf
[
12
]
&
0xff
)
<<
8
)
PT
.
name
,
buf
[
2
]
&
0xf
,
buf
[
12
],
buf
[
13
]);
|
((
buf
[
13
]
&
0xff
)
<<
16
)
;
PT
.
last_sense
=
(
buf
[
2
]
&
0xf
)
|
((
buf
[
12
]
&
0xff
)
<<
8
)
}
|
((
buf
[
13
]
&
0xff
)
<<
16
);
}
}
}
static
int
pt_atapi
(
int
unit
,
char
*
cmd
,
int
dlen
,
char
*
buf
,
char
*
fun
)
static
int
pt_atapi
(
int
unit
,
char
*
cmd
,
int
dlen
,
char
*
buf
,
char
*
fun
)
{
int
r
;
{
int
r
;
r
=
pt_command
(
unit
,
cmd
,
dlen
,
fun
);
mdelay
(
1
);
if
(
!
r
)
r
=
pt_completion
(
unit
,
buf
,
fun
);
if
(
r
)
pt_req_sense
(
unit
,
!
fun
);
r
=
pt_command
(
unit
,
cmd
,
dlen
,
fun
);
return
r
;
mdelay
(
1
);
if
(
!
r
)
r
=
pt_completion
(
unit
,
buf
,
fun
);
if
(
r
)
pt_req_sense
(
unit
,
!
fun
);
return
r
;
}
}
static
void
pt_sleep
(
int
cs
)
static
void
pt_sleep
(
int
cs
)
{
{
current
->
state
=
TASK_INTERRUPTIBLE
;
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
cs
);
schedule_timeout
(
cs
);
}
}
static
int
pt_poll_dsc
(
int
unit
,
int
pause
,
int
tmo
,
char
*
msg
)
static
int
pt_poll_dsc
(
int
unit
,
int
pause
,
int
tmo
,
char
*
msg
)
{
{
int
k
,
e
,
s
;
int
k
,
e
,
s
;
k
=
0
;
e
=
0
;
s
=
0
;
k
=
0
;
e
=
0
;
s
=
0
;
while
(
k
<
tmo
)
{
while
(
k
<
tmo
)
{
pt_sleep
(
pause
);
pt_sleep
(
pause
);
k
++
;
k
++
;
pi_connect
(
PI
);
pi_connect
(
PI
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
6
,
DRIVE
);
s
=
read_reg
(
unit
,
7
);
s
=
read_reg
(
unit
,
7
);
e
=
read_reg
(
unit
,
1
);
e
=
read_reg
(
unit
,
1
);
pi_disconnect
(
PI
);
pi_disconnect
(
PI
);
if
(
s
&
(
STAT_ERR
|
STAT_SEEK
))
break
;
if
(
s
&
(
STAT_ERR
|
STAT_SEEK
))
break
;
}
}
if
((
k
>=
tmo
)
||
(
s
&
STAT_ERR
))
{
if
((
k
>=
tmo
)
||
(
s
&
STAT_ERR
))
{
if
(
k
>=
tmo
)
printk
(
"%s: %s DSC timeout
\n
"
,
PT
.
name
,
msg
);
if
(
k
>=
tmo
)
else
printk
(
"%s: %s stat=0x%x err=0x%x
\n
"
,
PT
.
name
,
msg
,
s
,
e
);
printk
(
"%s: %s DSC timeout
\n
"
,
PT
.
name
,
msg
);
pt_req_sense
(
unit
,
0
);
else
return
0
;
printk
(
"%s: %s stat=0x%x err=0x%x
\n
"
,
PT
.
name
,
msg
,
s
,
e
);
pt_req_sense
(
unit
,
0
);
return
0
;
}
}
return
1
;
return
1
;
}
}
static
void
pt_media_access_cmd
(
int
unit
,
int
tmo
,
char
*
cmd
,
char
*
fun
)
static
void
pt_media_access_cmd
(
int
unit
,
int
tmo
,
char
*
cmd
,
char
*
fun
)
{
{
if
(
pt_command
(
unit
,
cmd
,
0
,
fun
))
{
if
(
pt_command
(
unit
,
cmd
,
0
,
fun
))
{
pt_req_sense
(
unit
,
0
);
pt_req_sense
(
unit
,
0
);
return
;
return
;
}
}
pi_disconnect
(
PI
);
pi_disconnect
(
PI
);
pt_poll_dsc
(
unit
,
HZ
,
tmo
,
fun
);
pt_poll_dsc
(
unit
,
HZ
,
tmo
,
fun
);
}
}
static
void
pt_rewind
(
int
unit
)
static
void
pt_rewind
(
int
unit
)
{
{
char
rw_cmd
[
12
]
=
{
ATAPI_REWIND
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
rw_cmd
[
12
]
=
{
ATAPI_REWIND
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
pt_media_access_cmd
(
unit
,
PT_REWIND_TMO
,
rw_cmd
,
"rewind"
);
pt_media_access_cmd
(
unit
,
PT_REWIND_TMO
,
rw_cmd
,
"rewind"
);
}
}
static
void
pt_write_fm
(
int
unit
)
static
void
pt_write_fm
(
int
unit
)
{
{
char
wm_cmd
[
12
]
=
{
ATAPI_WFM
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
wm_cmd
[
12
]
=
{
ATAPI_WFM
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
pt_media_access_cmd
(
unit
,
PT_TMO
,
wm_cmd
,
"write filemark"
);
pt_media_access_cmd
(
unit
,
PT_TMO
,
wm_cmd
,
"write filemark"
);
}
}
#define DBMSG(msg) ((verbose>1)?(msg):NULL)
#define DBMSG(msg) ((verbose>1)?(msg):NULL)
static
int
pt_reset
(
int
unit
)
static
int
pt_reset
(
int
unit
)
{
{
int
i
,
k
,
flg
;
int
i
,
k
,
flg
;
int
expect
[
5
]
=
{
1
,
1
,
1
,
0x14
,
0xeb
};
int
expect
[
5
]
=
{
1
,
1
,
1
,
0x14
,
0xeb
};
pi_connect
(
PI
);
pi_connect
(
PI
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
7
,
8
);
write_reg
(
unit
,
7
,
8
);
pt_sleep
(
20
*
HZ
/
1000
);
pt_sleep
(
20
*
HZ
/
1000
);
k
=
0
;
k
=
0
;
while
((
k
++
<
PT_RESET_TMO
)
&&
(
status_reg
(
unit
)
&
STAT_BUSY
))
while
((
k
++
<
PT_RESET_TMO
)
&&
(
status_reg
(
unit
)
&
STAT_BUSY
))
pt_sleep
(
HZ
/
10
);
pt_sleep
(
HZ
/
10
);
flg
=
1
;
flg
=
1
;
for
(
i
=
0
;
i
<
5
;
i
++
)
flg
&=
(
read_reg
(
unit
,
i
+
1
)
==
expect
[
i
]);
for
(
i
=
0
;
i
<
5
;
i
++
)
flg
&=
(
read_reg
(
unit
,
i
+
1
)
==
expect
[
i
]);
if
(
verbose
)
{
if
(
verbose
)
{
printk
(
"%s: Reset (%d) signature = "
,
PT
.
name
,
k
);
printk
(
"%s: Reset (%d) signature = "
,
PT
.
name
,
k
);
for
(
i
=
0
;
i
<
5
;
i
++
)
printk
(
"%3x"
,
read_reg
(
unit
,
i
+
1
));
for
(
i
=
0
;
i
<
5
;
i
++
)
if
(
!
flg
)
printk
(
" (incorrect)"
);
printk
(
"%3x"
,
read_reg
(
unit
,
i
+
1
));
if
(
!
flg
)
printk
(
" (incorrect)"
);
printk
(
"
\n
"
);
printk
(
"
\n
"
);
}
}
pi_disconnect
(
PI
);
pi_disconnect
(
PI
);
return
flg
-
1
;
return
flg
-
1
;
}
}
static
int
pt_ready_wait
(
int
unit
,
int
tmo
)
static
int
pt_ready_wait
(
int
unit
,
int
tmo
)
{
{
char
tr_cmd
[
12
]
=
{
ATAPI_TEST_READY
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
tr_cmd
[
12
]
=
{
ATAPI_TEST_READY
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
int
k
,
p
;
int
k
,
p
;
k
=
0
;
k
=
0
;
while
(
k
<
tmo
)
{
while
(
k
<
tmo
)
{
PT
.
last_sense
=
0
;
PT
.
last_sense
=
0
;
pt_atapi
(
unit
,
tr_cmd
,
0
,
NULL
,
DBMSG
(
"test unit ready"
));
pt_atapi
(
unit
,
tr_cmd
,
0
,
NULL
,
DBMSG
(
"test unit ready"
));
p
=
PT
.
last_sense
;
p
=
PT
.
last_sense
;
if
(
!
p
)
return
0
;
if
(
!
p
)
if
(
!
(((
p
&
0xffff
)
==
0x0402
)
||
((
p
&
0xff
)
==
6
)))
return
p
;
return
0
;
k
++
;
if
(
!
(((
p
&
0xffff
)
==
0x0402
)
||
((
p
&
0xff
)
==
6
)))
pt_sleep
(
HZ
);
return
p
;
k
++
;
pt_sleep
(
HZ
);
}
}
return
0x000020
;
/* timeout */
return
0x000020
;
/* timeout */
}
}
static
void
xs
(
char
*
buf
,
char
*
targ
,
int
offs
,
int
len
)
static
void
xs
(
char
*
buf
,
char
*
targ
,
int
offs
,
int
len
)
{
{
int
j
,
k
,
l
;
int
j
,
k
,
l
;
j
=
0
;
l
=
0
;
j
=
0
;
for
(
k
=
0
;
k
<
len
;
k
++
)
l
=
0
;
if
((
buf
[
k
+
offs
]
!=
0x20
)
||
(
buf
[
k
+
offs
]
!=
l
))
for
(
k
=
0
;
k
<
len
;
k
++
)
l
=
targ
[
j
++
]
=
buf
[
k
+
offs
];
if
((
buf
[
k
+
offs
]
!=
0x20
)
||
(
buf
[
k
+
offs
]
!=
l
))
if
(
l
==
0x20
)
j
--
;
l
=
targ
[
j
++
]
=
buf
[
k
+
offs
];
targ
[
j
]
=
0
;
if
(
l
==
0x20
)
j
--
;
targ
[
j
]
=
0
;
}
}
static
int
xn
(
char
*
buf
,
int
offs
,
int
size
)
static
int
xn
(
char
*
buf
,
int
offs
,
int
size
)
{
{
int
v
,
k
;
int
v
,
k
;
v
=
0
;
v
=
0
;
for
(
k
=
0
;
k
<
size
;
k
++
)
v
=
v
*
256
+
(
buf
[
k
+
offs
]
&
0xff
);
for
(
k
=
0
;
k
<
size
;
k
++
)
v
=
v
*
256
+
(
buf
[
k
+
offs
]
&
0xff
);
return
v
;
return
v
;
}
}
static
int
pt_identify
(
int
unit
)
static
int
pt_identify
(
int
unit
)
{
{
int
dt
,
s
;
int
dt
,
s
;
char
*
ms
[
2
]
=
{
"master"
,
"slave"
};
char
*
ms
[
2
]
=
{
"master"
,
"slave"
};
char
mf
[
10
],
id
[
18
];
char
mf
[
10
],
id
[
18
];
char
id_cmd
[
12
]
=
{
ATAPI_IDENTIFY
,
0
,
0
,
0
,
36
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
id_cmd
[
12
]
=
{
ATAPI_IDENTIFY
,
0
,
0
,
0
,
36
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
ms_cmd
[
12
]
=
{
ATAPI_MODE_SENSE
,
0
,
0x2a
,
0
,
36
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
ms_cmd
[
12
]
=
char
ls_cmd
[
12
]
=
{
ATAPI_LOG_SENSE
,
0
,
0x71
,
0
,
0
,
0
,
0
,
0
,
36
,
0
,
0
,
0
};
{
ATAPI_MODE_SENSE
,
0
,
0x2a
,
0
,
36
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
buf
[
36
];
char
ls_cmd
[
12
]
=
{
ATAPI_LOG_SENSE
,
0
,
0x71
,
0
,
0
,
0
,
0
,
0
,
36
,
0
,
0
,
0
};
s
=
pt_atapi
(
unit
,
id_cmd
,
36
,
buf
,
"identify"
);
char
buf
[
36
];
if
(
s
)
return
-
1
;
s
=
pt_atapi
(
unit
,
id_cmd
,
36
,
buf
,
"identify"
);
if
(
s
)
return
-
1
;
dt
=
buf
[
0
]
&
0x1f
;
dt
=
buf
[
0
]
&
0x1f
;
if
(
dt
!=
1
)
{
if
(
dt
!=
1
)
{
if
(
verbose
)
if
(
verbose
)
printk
(
"%s: Drive %d, unsupported type %d
\n
"
,
printk
(
"%s: Drive %d, unsupported type %d
\n
"
,
PT
.
name
,
PT
.
drive
,
dt
);
PT
.
name
,
PT
.
drive
,
dt
);
return
-
1
;
return
-
1
;
}
}
xs
(
buf
,
mf
,
8
,
8
);
xs
(
buf
,
mf
,
8
,
8
);
xs
(
buf
,
id
,
16
,
16
);
xs
(
buf
,
id
,
16
,
16
);
PT
.
flags
=
0
;
PT
.
flags
=
0
;
PT
.
capacity
=
0
;
PT
.
capacity
=
0
;
PT
.
bs
=
0
;
PT
.
bs
=
0
;
if
(
!
pt_ready_wait
(
unit
,
PT_READY_TMO
))
PT
.
flags
|=
PT_MEDIA
;
if
(
!
pt_ready_wait
(
unit
,
PT_READY_TMO
))
PT
.
flags
|=
PT_MEDIA
;
if
(
!
pt_atapi
(
unit
,
ms_cmd
,
36
,
buf
,
"mode sense"
))
{
if
(
!
pt_atapi
(
unit
,
ms_cmd
,
36
,
buf
,
"mode sense"
))
{
if
(
!
(
buf
[
2
]
&
0x80
))
PT
.
flags
|=
PT_WRITE_OK
;
if
(
!
(
buf
[
2
]
&
0x80
))
PT
.
bs
=
xn
(
buf
,
10
,
2
);
PT
.
flags
|=
PT_WRITE_OK
;
PT
.
bs
=
xn
(
buf
,
10
,
2
);
}
}
if
(
!
pt_atapi
(
unit
,
ls_cmd
,
36
,
buf
,
"log sense"
))
if
(
!
pt_atapi
(
unit
,
ls_cmd
,
36
,
buf
,
"log sense"
))
PT
.
capacity
=
xn
(
buf
,
24
,
4
);
PT
.
capacity
=
xn
(
buf
,
24
,
4
);
printk
(
"%s: %s %s, %s"
,
printk
(
"%s: %s %s, %s"
,
PT
.
name
,
mf
,
id
,
ms
[
PT
.
drive
]);
PT
.
name
,
mf
,
id
,
ms
[
PT
.
drive
]);
if
(
!
(
PT
.
flags
&
PT_MEDIA
))
if
(
!
(
PT
.
flags
&
PT_MEDIA
))
printk
(
", no media
\n
"
);
printk
(
", no media
\n
"
);
else
{
else
{
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
printk
(
", RO"
);
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
printk
(
", blocksize %d, %d MB
\n
"
,
printk
(
", RO"
);
PT
.
bs
,
PT
.
capacity
/
1024
);
printk
(
", blocksize %d, %d MB
\n
"
,
PT
.
bs
,
PT
.
capacity
/
1024
);
}
}
return
0
;
return
0
;
}
}
static
int
pt_probe
(
int
unit
)
/* returns 0, with id set if drive is detected
/*
-1, if drive detection failed
* returns 0, with id set if drive is detected
*/
* -1, if drive detection failed
*/
{
if
(
PT
.
drive
==
-
1
)
{
static
int
pt_probe
(
int
unit
)
for
(
PT
.
drive
=
0
;
PT
.
drive
<=
1
;
PT
.
drive
++
)
{
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
if
(
PT
.
drive
==
-
1
)
{
for
(
PT
.
drive
=
0
;
PT
.
drive
<=
1
;
PT
.
drive
++
)
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
}
else
{
}
else
{
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
}
}
return
-
1
;
return
-
1
;
}
}
static
int
pt_detect
(
void
)
static
int
pt_detect
(
void
)
{
{
int
k
,
unit
;
int
k
,
unit
;
printk
(
"%s: %s version %s, major %d
\n
"
,
printk
(
"%s: %s version %s, major %d
\n
"
,
name
,
name
,
PT_VERSION
,
major
);
name
,
name
,
PT_VERSION
,
major
);
k
=
0
;
k
=
0
;
if
(
pt_drive_count
==
0
)
{
if
(
pt_drive_count
==
0
)
{
unit
=
0
;
unit
=
0
;
if
(
pi_init
(
PI
,
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
pt_scratch
,
if
(
pi_init
(
PI
,
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
pt_scratch
,
PI_PT
,
verbose
,
PT
.
name
))
{
PI_PT
,
verbose
,
PT
.
name
))
{
if
(
!
pt_probe
(
unit
))
{
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
PT
.
present
=
1
;
k
++
;
k
++
;
}
else
pi_release
(
PI
);
}
else
}
pi_release
(
PI
);
}
}
else
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
DU
[
D_PRT
])
if
(
pi_init
(
PI
,
0
,
DU
[
D_PRT
],
DU
[
D_MOD
],
DU
[
D_UNI
],
}
else
DU
[
D_PRO
],
DU
[
D_DLY
],
pt_scratch
,
PI_PT
,
verbose
,
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
PT
.
name
))
{
if
(
DU
[
D_PRT
])
if
(
!
pt_probe
(
unit
))
{
if
(
pi_init
PT
.
present
=
1
;
(
PI
,
0
,
DU
[
D_PRT
],
DU
[
D_MOD
],
DU
[
D_UNI
],
k
++
;
DU
[
D_PRO
],
DU
[
D_DLY
],
pt_scratch
,
PI_PT
,
}
else
pi_release
(
PI
);
verbose
,
PT
.
name
))
{
}
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
if
(
k
)
return
0
;
k
++
;
}
else
printk
(
"%s: No ATAPI tape drive detected
\n
"
,
name
);
pi_release
(
PI
);
}
if
(
k
)
return
0
;
printk
(
"%s: No ATAPI tape drive detected
\n
"
,
name
);
return
-
1
;
return
-
1
;
}
}
#define DEVICE_NR(dev) (minor(dev) & 0x7F)
#define DEVICE_NR(dev) (minor(dev) & 0x7F)
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
int
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
int
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
if
((
unit
>=
PT_UNITS
)
||
(
!
PT
.
present
))
return
-
ENODEV
;
if
((
unit
>=
PT_UNITS
)
||
(
!
PT
.
present
))
return
-
ENODEV
;
if
(
!
atomic_dec_and_test
(
&
PT
.
available
)
)
{
if
(
!
atomic_dec_and_test
(
&
PT
.
available
)
)
{
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
pt_identify
(
unit
);
pt_identify
(
unit
);
if
(
!
PT
.
flags
&
PT_MEDIA
)
{
if
(
!
PT
.
flags
&
PT_MEDIA
)
{
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
if
((
!
PT
.
flags
&
PT_WRITE_OK
)
&&
(
file
->
f_mode
&
2
))
{
if
((
!
PT
.
flags
&
PT_WRITE_OK
)
&&
(
file
->
f_mode
&
2
))
{
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
-
EROFS
;
return
-
EROFS
;
}
}
if
(
!
(
minor
(
inode
->
i_rdev
)
&
128
))
if
(
!
(
minor
(
inode
->
i_rdev
)
&
128
))
PT
.
flags
|=
PT_REWIND
;
PT
.
flags
|=
PT_REWIND
;
PT
.
bufptr
=
kmalloc
(
PT_BUFSIZE
,
GFP_KERNEL
);
PT
.
bufptr
=
kmalloc
(
PT_BUFSIZE
,
GFP_KERNEL
);
if
(
PT
.
bufptr
==
NULL
)
{
if
(
PT
.
bufptr
==
NULL
)
{
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
printk
(
"%s: buffer allocation failed
\n
"
,
PT
.
name
);
printk
(
"%s: buffer allocation failed
\n
"
,
PT
.
name
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
return
0
;
return
0
;
}
}
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
unsigned
int
cmd
,
unsigned
long
arg
)
{
{
int
unit
;
int
unit
;
struct
mtop
mtop
;
struct
mtop
mtop
;
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
if
(
unit
>=
PT_UNITS
)
if
(
unit
>=
PT_UNITS
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
PT
.
present
)
if
(
!
PT
.
present
)
return
-
ENODEV
;
return
-
ENODEV
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
MTIOCTOP
:
case
MTIOCTOP
:
if
(
copy_from_user
((
char
*
)
&
mtop
,
(
char
*
)
arg
,
if
(
copy_from_user
((
char
*
)
&
mtop
,
(
char
*
)
arg
,
sizeof
(
struct
mtop
)))
return
-
EFAULT
;
sizeof
(
struct
mtop
)))
return
-
EFAULT
;
switch
(
mtop
.
mt_op
)
{
switch
(
mtop
.
mt_op
)
{
case
MTREW
:
case
MTREW
:
pt_rewind
(
unit
);
pt_rewind
(
unit
);
return
0
;
return
0
;
case
MTWEOF
:
case
MTWEOF
:
pt_write_fm
(
unit
);
pt_write_fm
(
unit
);
return
0
;
return
0
;
default:
default:
printk
(
"%s: Unimplemented mt_op %d
\n
"
,
PT
.
name
,
printk
(
"%s: Unimplemented mt_op %d
\n
"
,
PT
.
name
,
mtop
.
mt_op
);
mtop
.
mt_op
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
default:
default:
printk
(
"%s: Unimplemented ioctl 0x%x
\n
"
,
PT
.
name
,
cmd
);
printk
(
"%s: Unimplemented ioctl 0x%x
\n
"
,
PT
.
name
,
cmd
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
}
}
static
int
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
)
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
int
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
int
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
if
((
unit
>=
PT_UNITS
)
||
(
atomic_read
(
&
PT
.
available
)
>
1
))
if
((
unit
>=
PT_UNITS
)
||
(
atomic_read
(
&
PT
.
available
)
>
1
))
return
-
EINVAL
;
return
-
EINVAL
;
if
(
PT
.
flags
&
PT_WRITING
)
pt_write_fm
(
unit
);
if
(
PT
.
flags
&
PT_WRITING
)
pt_write_fm
(
unit
);
if
(
PT
.
flags
&
PT_REWIND
)
pt_rewind
(
unit
);
if
(
PT
.
flags
&
PT_REWIND
)
pt_rewind
(
unit
);
kfree
(
PT
.
bufptr
);
kfree
(
PT
.
bufptr
);
PT
.
bufptr
=
NULL
;
PT
.
bufptr
=
NULL
;
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
0
;
return
0
;
}
}
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
{
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
int
unit
=
DEVICE_NR
(
ino
->
i_rdev
);
int
unit
=
DEVICE_NR
(
ino
->
i_rdev
);
char
rd_cmd
[
12
]
=
{
ATAPI_READ_6
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
rd_cmd
[
12
]
=
{
ATAPI_READ_6
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
PT
.
flags
|=
PT_READING
;
PT
.
flags
|=
PT_READING
;
if
(
pt_atapi
(
unit
,
rd_cmd
,
0
,
NULL
,
"start read-ahead"
))
if
(
pt_atapi
(
unit
,
rd_cmd
,
0
,
NULL
,
"start read-ahead"
))
return
-
EIO
;
return
-
EIO
;
}
else
if
(
PT
.
flags
&
PT_WRITING
)
return
-
EIO
;
}
else
if
(
PT
.
flags
&
PT_WRITING
)
return
-
EIO
;
if
(
PT
.
flags
&
PT_EOF
)
return
0
;
if
(
PT
.
flags
&
PT_EOF
)
return
0
;
t
=
0
;
t
=
0
;
while
(
count
>
0
)
{
while
(
count
>
0
)
{
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"read"
))
return
-
EIO
;
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"read"
))
return
-
EIO
;
n
=
count
;
if
(
n
>
32768
)
n
=
32768
;
/* max per command */
b
=
(
n
-
1
+
PT
.
bs
)
/
PT
.
bs
;
n
=
b
*
PT
.
bs
;
/* rounded up to even block */
rd_cmd
[
4
]
=
b
;
r
=
pt_command
(
unit
,
rd_cmd
,
n
,
"read"
);
mdelay
(
1
);
if
(
r
)
{
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
while
(
1
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
n
=
count
;
DBMSG
(
"read DRQ"
),
""
);
if
(
n
>
32768
)
n
=
32768
;
/* max per command */
b
=
(
n
-
1
+
PT
.
bs
)
/
PT
.
bs
;
n
=
b
*
PT
.
bs
;
/* rounded up to even block */
if
(
r
&
STAT_SENSE
)
{
rd_cmd
[
4
]
=
b
;
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
if
(
r
)
PT
.
flags
|=
PT_EOF
;
r
=
pt_command
(
unit
,
rd_cmd
,
n
,
"read"
);
s
=
read_reg
(
unit
,
7
);
mdelay
(
1
);
if
(
!
(
s
&
STAT_DRQ
))
break
;
if
(
r
)
{
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
n
=
(
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
));
while
(
1
)
{
p
=
(
read_reg
(
unit
,
2
)
&
3
);
if
(
p
!=
2
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
pi_disconnect
(
PI
);
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
printk
(
"%s: Phase error on read: %d
\n
"
,
PT
.
name
,
p
);
DBMSG
(
"read DRQ"
),
""
);
return
-
EIO
;
}
if
(
r
&
STAT_SENSE
)
{
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
if
(
r
)
PT
.
flags
|=
PT_EOF
;
s
=
read_reg
(
unit
,
7
);
if
(
!
(
s
&
STAT_DRQ
))
break
;
n
=
(
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
));
p
=
(
read_reg
(
unit
,
2
)
&
3
);
if
(
p
!=
2
)
{
pi_disconnect
(
PI
);
printk
(
"%s: Phase error on read: %d
\n
"
,
PT
.
name
,
p
);
return
-
EIO
;
}
while
(
n
>
0
)
{
k
=
n
;
if
(
k
>
PT_BUFSIZE
)
k
=
PT_BUFSIZE
;
pi_read_block
(
PI
,
PT
.
bufptr
,
k
);
n
-=
k
;
b
=
k
;
if
(
b
>
count
)
b
=
count
;
if
(
copy_to_user
(
buf
+
t
,
PT
.
bufptr
,
b
))
{
pi_disconnect
(
PI
);
return
-
EFAULT
;
}
t
+=
b
;
count
-=
b
;
}
while
(
n
>
0
)
{
}
k
=
n
;
pi_disconnect
(
PI
);
if
(
k
>
PT_BUFSIZE
)
k
=
PT_BUFSIZE
;
if
(
PT
.
flags
&
PT_EOF
)
pi_read_block
(
PI
,
PT
.
bufptr
,
k
);
break
;
n
-=
k
;
b
=
k
;
if
(
b
>
count
)
b
=
count
;
if
(
copy_to_user
(
buf
+
t
,
PT
.
bufptr
,
b
))
{
pi_disconnect
(
PI
);
return
-
EFAULT
;
}
t
+=
b
;
count
-=
b
;
}
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
}
return
t
;
return
t
;
}
}
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
{
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
int
unit
=
DEVICE_NR
(
ino
->
i_rdev
);
int
unit
=
DEVICE_NR
(
ino
->
i_rdev
);
char
wr_cmd
[
12
]
=
{
ATAPI_WRITE_6
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
wr_cmd
[
12
]
=
{
ATAPI_WRITE_6
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
return
-
EROFS
;
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
return
-
EROFS
;
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
PT
.
flags
|=
PT_WRITING
;
PT
.
flags
|=
PT_WRITING
;
if
(
pt_atapi
(
unit
,
wr_cmd
,
0
,
NULL
,
"start buffer-available mode"
))
if
(
pt_atapi
return
-
EIO
;
(
unit
,
wr_cmd
,
0
,
NULL
,
"start buffer-available mode"
))
}
else
if
(
PT
.
flags
&
PT_READING
)
return
-
EIO
;
return
-
EIO
;
}
else
if
(
PT
.
flags
&
PT_READING
)
return
-
EIO
;
if
(
PT
.
flags
&
PT_EOF
)
return
-
ENOSPC
;
if
(
PT
.
flags
&
PT_EOF
)
return
-
ENOSPC
;
t
=
0
;
t
=
0
;
while
(
count
>
0
)
{
while
(
count
>
0
)
{
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"write"
))
return
-
EIO
;
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"write"
))
return
-
EIO
;
n
=
count
;
if
(
n
>
32768
)
n
=
32768
;
/* max per command */
b
=
(
n
-
1
+
PT
.
bs
)
/
PT
.
bs
;
n
=
b
*
PT
.
bs
;
/* rounded up to even block */
wr_cmd
[
4
]
=
b
;
r
=
pt_command
(
unit
,
wr_cmd
,
n
,
"write"
);
mdelay
(
1
);
if
(
r
)
{
/* error delivering command only */
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
while
(
1
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
n
=
count
;
DBMSG
(
"write DRQ"
),
NULL
);
if
(
n
>
32768
)
n
=
32768
;
/* max per command */
b
=
(
n
-
1
+
PT
.
bs
)
/
PT
.
bs
;
n
=
b
*
PT
.
bs
;
/* rounded up to even block */
if
(
r
&
STAT_SENSE
)
{
wr_cmd
[
4
]
=
b
;
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
if
(
r
)
PT
.
flags
|=
PT_EOF
;
r
=
pt_command
(
unit
,
wr_cmd
,
n
,
"write"
)
;
s
=
read_reg
(
unit
,
7
);
mdelay
(
1
);
if
(
!
(
s
&
STAT_DRQ
))
break
;
if
(
r
)
{
/* error delivering command only */
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
n
=
(
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
));
while
(
1
)
{
p
=
(
read_reg
(
unit
,
2
)
&
3
);
if
(
p
!=
0
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
pi_disconnect
(
PI
);
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
printk
(
"%s: Phase error on write: %d
\n
"
,
PT
.
name
,
p
);
DBMSG
(
"write DRQ"
),
NULL
);
return
-
EIO
;
}
if
(
r
&
STAT_SENSE
)
{
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
if
(
r
)
PT
.
flags
|=
PT_EOF
;
s
=
read_reg
(
unit
,
7
);
if
(
!
(
s
&
STAT_DRQ
))
break
;
n
=
(
read_reg
(
unit
,
4
)
+
256
*
read_reg
(
unit
,
5
));
p
=
(
read_reg
(
unit
,
2
)
&
3
);
if
(
p
!=
0
)
{
pi_disconnect
(
PI
);
printk
(
"%s: Phase error on write: %d
\n
"
,
PT
.
name
,
p
);
return
-
EIO
;
}
while
(
n
>
0
)
{
k
=
n
;
if
(
k
>
PT_BUFSIZE
)
k
=
PT_BUFSIZE
;
b
=
k
;
if
(
b
>
count
)
b
=
count
;
if
(
copy_from_user
(
PT
.
bufptr
,
buf
+
t
,
b
))
{
pi_disconnect
(
PI
);
return
-
EFAULT
;
}
pi_write_block
(
PI
,
PT
.
bufptr
,
k
);
t
+=
b
;
count
-=
b
;
n
-=
k
;
}
while
(
n
>
0
)
{
}
k
=
n
;
pi_disconnect
(
PI
);
if
(
k
>
PT_BUFSIZE
)
k
=
PT_BUFSIZE
;
if
(
PT
.
flags
&
PT_EOF
)
b
=
k
;
break
;
if
(
b
>
count
)
b
=
count
;
if
(
copy_from_user
(
PT
.
bufptr
,
buf
+
t
,
b
))
{
pi_disconnect
(
PI
);
return
-
EFAULT
;
}
pi_write_block
(
PI
,
PT
.
bufptr
,
k
);
t
+=
b
;
count
-=
b
;
n
-=
k
;
}
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
}
return
t
;
return
t
;
...
@@ -915,23 +982,23 @@ static int __init pt_init(void)
...
@@ -915,23 +982,23 @@ static int __init pt_init(void)
if
(
pt_detect
())
if
(
pt_detect
())
return
-
1
;
return
-
1
;
if
(
register_chrdev
(
major
,
name
,
&
pt_fops
))
{
if
(
register_chrdev
(
major
,
name
,
&
pt_fops
))
{
printk
(
"pt_init: unable to get major number %d
\n
"
,
printk
(
"pt_init: unable to get major number %d
\n
"
,
major
);
major
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
if
(
PT
.
present
)
pi_release
(
PI
);
pi_release
(
PI
);
return
-
1
;
return
-
1
;
}
}
devfs_mk_dir
(
"pt"
);
devfs_mk_dir
(
"pt"
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
{
if
(
PT
.
present
)
{
devfs_mk_cdev
(
MKDEV
(
major
,
unit
),
devfs_mk_cdev
(
MKDEV
(
major
,
unit
),
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%d"
,
unit
);
"pt/%d"
,
unit
);
devfs_mk_cdev
(
MKDEV
(
major
,
unit
+
128
),
devfs_mk_cdev
(
MKDEV
(
major
,
unit
+
128
),
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%dn"
,
unit
);
"pt/%dn"
,
unit
);
}
}
return
0
;
return
0
;
}
}
...
@@ -939,14 +1006,14 @@ static int __init pt_init(void)
...
@@ -939,14 +1006,14 @@ static int __init pt_init(void)
static
void
__exit
pt_exit
(
void
)
static
void
__exit
pt_exit
(
void
)
{
{
int
unit
;
int
unit
;
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
{
if
(
PT
.
present
)
{
devfs_remove
(
"pt/%d"
,
unit
);
devfs_remove
(
"pt/%d"
,
unit
);
devfs_remove
(
"pt/%dn"
,
unit
);
devfs_remove
(
"pt/%dn"
,
unit
);
}
}
devfs_remove
(
"pt"
);
devfs_remove
(
"pt"
);
unregister_chrdev
(
major
,
name
);
unregister_chrdev
(
major
,
name
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
if
(
PT
.
present
)
pi_release
(
PI
);
pi_release
(
PI
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment