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
Kirill Smelkov
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 @@
*/
static
int
verbose
=
0
;
static
int
major
=
PT_MAJOR
;
static
char
*
name
=
PT_NAME
;
static
int
disable
=
0
;
static
int
verbose
=
0
;
static
int
major
=
PT_MAJOR
;
static
char
*
name
=
PT_NAME
;
static
int
disable
=
0
;
static
int
drive0
[
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
drive3
[
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
drive2
[
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
;
#define D_PRT 0
...
...
@@ -139,7 +139,6 @@ static int pt_drive_count;
/* end of parameters */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
...
...
@@ -154,37 +153,40 @@ static int pt_drive_count;
#include "setup.h"
static
STT
pt_stt
[
5
]
=
{
{
"drive0"
,
6
,
drive0
},
{
"drive1"
,
6
,
drive1
},
{
"drive2"
,
6
,
drive2
},
{
"drive3"
,
6
,
drive3
},
{
"disable"
,
1
,
&
disable
}};
void
pt_setup
(
char
*
str
,
int
*
ints
)
static
STT
pt_stt
[
5
]
=
{
{
"drive0"
,
6
,
drive0
},
{
"drive1"
,
6
,
drive1
},
{
"drive2"
,
6
,
drive2
},
{
"drive3"
,
6
,
drive3
},
{
"disable"
,
1
,
&
disable
}
};
{
generic_setup
(
pt_stt
,
5
,
str
);
void
pt_setup
(
char
*
str
,
int
*
ints
)
{
generic_setup
(
pt_stt
,
5
,
str
);
}
#endif
MODULE_PARM
(
verbose
,
"i"
);
MODULE_PARM
(
major
,
"i"
);
MODULE_PARM
(
name
,
"s"
);
MODULE_PARM
(
drive0
,
"1-6i"
);
MODULE_PARM
(
drive1
,
"1-6i"
);
MODULE_PARM
(
drive2
,
"1-6i"
);
MODULE_PARM
(
drive3
,
"1-6i"
);
MODULE_PARM
(
verbose
,
"i"
);
MODULE_PARM
(
major
,
"i"
);
MODULE_PARM
(
name
,
"s"
);
MODULE_PARM
(
drive0
,
"1-6i"
);
MODULE_PARM
(
drive1
,
"1-6i"
);
MODULE_PARM
(
drive2
,
"1-6i"
);
MODULE_PARM
(
drive3
,
"1-6i"
);
#include "paride.h"
#define PT_MAX_RETRIES 5
#define PT_TMO 3000
/* interrupt timeout in jiffies */
#define PT_SPIN_DEL 50
/* spin delay in micro-seconds */
#define PT_RESET_TMO 30
/* 30 seconds */
#define PT_READY_TMO 60
/* 60 seconds */
#define PT_REWIND_TMO 1200
/* 20 minutes */
#define PT_TMO 3000
/* interrupt timeout in jiffies */
#define PT_SPIN_DEL 50
/* spin delay in micro-seconds */
#define PT_RESET_TMO 30
/* 30 seconds */
#define PT_READY_TMO 60
/* 60 seconds */
#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_INDEX 0x00002
...
...
@@ -207,16 +209,16 @@ MODULE_PARM(drive3,"1-6i");
#define ATAPI_LOG_SENSE 0x4d
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
static
int
pt_detect
(
void
);
static
int
pt_identify
(
int
unit
);
static
int
pt_identify
(
int
unit
);
/* bits in PT.flags */
...
...
@@ -231,18 +233,18 @@ static int pt_identify (int unit);
#define PT_BUFSIZE 16384
struct
pt_unit
{
struct
pi_adapter
pia
;
/* interface to paride layer */
struct
pi_adapter
pia
;
/* interface to paride layer */
struct
pi_adapter
*
pi
;
int
flags
;
/* various state flags */
int
last_sense
;
/* result of last request sense */
int
drive
;
/* drive */
atomic_t
available
;
/* 1 if access is available 0 otherwise */
int
bs
;
/* block size */
int
capacity
;
/* Size of tape in KB */
int
present
;
/* device present ? */
int
flags
;
/* various state flags */
int
last_sense
;
/* result of last request sense */
int
drive
;
/* drive */
atomic_t
available
;
/* 1 if access is available 0 otherwise */
int
bs
;
/* block size */
int
capacity
;
/* Size of tape in KB */
int
present
;
/* device present ? */
char
*
bufptr
;
char
name
[
PT_NAMELEN
];
/* pf0, pf1, ... */
};
char
name
[
PT_NAMELEN
];
/* pf0, pf1, ... */
};
struct
pt_unit
pt
[
PT_UNITS
];
...
...
@@ -251,38 +253,40 @@ struct pt_unit pt[PT_UNITS];
#define PT pt[unit]
#define PI PT.pi
static
char
pt_scratch
[
512
];
/* scratch block buffer */
static
char
pt_scratch
[
512
];
/* scratch block buffer */
/* kernel glue structures */
static
struct
file_operations
pt_fops
=
{
.
owner
=
THIS_MODULE
,
.
read
=
pt_read
,
.
write
=
pt_write
,
.
ioctl
=
pt_ioctl
,
.
open
=
pt_open
,
.
release
=
pt_release
,
.
owner
=
THIS_MODULE
,
.
read
=
pt_read
,
.
write
=
pt_write
,
.
ioctl
=
pt_ioctl
,
.
open
=
pt_open
,
.
release
=
pt_release
,
};
void
pt_init_units
(
void
)
{
int
unit
,
j
;
static
void
pt_init_units
(
void
)
{
int
unit
,
j
;
pt_drive_count
=
0
;
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
{
PT
.
pi
=
&
PT
.
pia
;
atomic_set
(
&
PT
.
available
,
1
);
PT
.
flags
=
0
;
pt_drive_count
=
0
;
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
{
PT
.
pi
=
&
PT
.
pia
;
atomic_set
(
&
PT
.
available
,
1
);
PT
.
flags
=
0
;
PT
.
last_sense
=
0
;
PT
.
present
=
0
;
PT
.
present
=
0
;
PT
.
bufptr
=
NULL
;
PT
.
drive
=
DU
[
D_SLV
];
j
=
0
;
while
((
j
<
PT_NAMELEN
-
2
)
&&
(
PT
.
name
[
j
]
=
name
[
j
]))
j
++
;
PT
.
name
[
j
++
]
=
'0'
+
unit
;
PT
.
name
[
j
]
=
0
;
if
(
DU
[
D_PRT
])
pt_drive_count
++
;
}
j
=
0
;
while
((
j
<
PT_NAMELEN
-
2
)
&&
(
PT
.
name
[
j
]
=
name
[
j
]))
j
++
;
PT
.
name
[
j
++
]
=
'0'
+
unit
;
PT
.
name
[
j
]
=
0
;
if
(
DU
[
D_PRT
])
pt_drive_count
++
;
}
}
static
inline
int
status_reg
(
int
unit
)
...
...
@@ -302,602 +306,665 @@ static inline void write_reg(int unit, int reg, int val)
#define DRIVE (0xa0+0x10*PT.drive)
static
int
pt_wait
(
int
unit
,
int
go
,
int
stop
,
char
*
fun
,
char
*
msg
)
{
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
);
static
int
pt_wait
(
int
unit
,
int
go
,
int
stop
,
char
*
fun
,
char
*
msg
)
{
int
j
,
r
,
e
,
s
,
p
;
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"
))
{
pi_disconnect
(
PI
);
return
-
1
;
}
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
;
}
write_reg
(
unit
,
4
,
dlen
%
256
);
write_reg
(
unit
,
5
,
dlen
/
256
);
write_reg
(
unit
,
7
,
0xa0
);
/* ATAPI packet command */
static
int
pt_command
(
int
unit
,
char
*
cmd
,
int
dlen
,
char
*
fun
)
{
pi_connect
(
PI
);
if
(
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
,
fun
,
"command DRQ"
))
{
pi_disconnect
(
PI
);
return
-
1
;
}
write_reg
(
unit
,
6
,
DRIVE
);
if
(
read_reg
(
unit
,
2
)
!=
1
)
{
printk
(
"%s: %s: command phase error
\n
"
,
PT
.
name
,
fun
);
pi_disconnect
(
PI
);
return
-
1
;
}
if
(
pt_wait
(
unit
,
STAT_BUSY
|
STAT_DRQ
,
0
,
fun
,
"before command"
))
{
pi_disconnect
(
PI
);
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
,
fun
,
"completion"
);
return
0
;
}
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
);
}
static
int
pt_completion
(
int
unit
,
char
*
buf
,
char
*
fun
)
{
int
r
,
s
,
n
,
p
;
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
)
{
char
rs_cmd
[
12
]
=
{
ATAPI_REQ_SENSE
,
0
,
0
,
0
,
16
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
char
buf
[
16
];
int
r
;
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
buf
[
16
];
int
r
;
r
=
pt_command
(
unit
,
rs_cmd
,
16
,
"Request sense"
);
mdelay
(
1
);
if
(
!
r
)
pt_completion
(
unit
,
buf
,
"Request sense"
);
r
=
pt_command
(
unit
,
rs_cmd
,
16
,
"Request sense"
);
mdelay
(
1
);
if
(
!
r
)
pt_completion
(
unit
,
buf
,
"Request sense"
);
PT
.
last_sense
=
-
1
;
if
(
!
r
)
{
if
(
!
quiet
)
printk
(
"%s: Sense key: %x, ASC: %x, ASQ: %x
\n
"
,
PT
.
name
,
buf
[
2
]
&
0xf
,
buf
[
12
],
buf
[
13
]);
PT
.
last_sense
=
(
buf
[
2
]
&
0xf
)
|
((
buf
[
12
]
&
0xff
)
<<
8
)
|
((
buf
[
13
]
&
0xff
)
<<
16
)
;
}
if
(
!
r
)
{
if
(
!
quiet
)
printk
(
"%s: Sense key: %x, ASC: %x, ASQ: %x
\n
"
,
PT
.
name
,
buf
[
2
]
&
0xf
,
buf
[
12
],
buf
[
13
]);
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
);
mdelay
(
1
);
if
(
!
r
)
r
=
pt_completion
(
unit
,
buf
,
fun
);
if
(
r
)
pt_req_sense
(
unit
,
!
fun
);
return
r
;
return
r
;
}
static
void
pt_sleep
(
int
cs
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
cs
);
static
void
pt_sleep
(
int
cs
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
cs
);
}
static
int
pt_poll_dsc
(
int
unit
,
int
pause
,
int
tmo
,
char
*
msg
)
{
int
k
,
e
,
s
;
static
int
pt_poll_dsc
(
int
unit
,
int
pause
,
int
tmo
,
char
*
msg
)
{
int
k
,
e
,
s
;
k
=
0
;
e
=
0
;
s
=
0
;
k
=
0
;
e
=
0
;
s
=
0
;
while
(
k
<
tmo
)
{
pt_sleep
(
pause
);
k
++
;
pi_connect
(
PI
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
6
,
DRIVE
);
s
=
read_reg
(
unit
,
7
);
e
=
read_reg
(
unit
,
1
);
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
)
printk
(
"%s: %s DSC timeout
\n
"
,
PT
.
name
,
msg
);
else
printk
(
"%s: %s stat=0x%x err=0x%x
\n
"
,
PT
.
name
,
msg
,
s
,
e
);
pt_req_sense
(
unit
,
0
);
return
0
;
if
(
k
>=
tmo
)
printk
(
"%s: %s DSC timeout
\n
"
,
PT
.
name
,
msg
);
else
printk
(
"%s: %s stat=0x%x err=0x%x
\n
"
,
PT
.
name
,
msg
,
s
,
e
);
pt_req_sense
(
unit
,
0
);
return
0
;
}
return
1
;
}
static
void
pt_media_access_cmd
(
int
unit
,
int
tmo
,
char
*
cmd
,
char
*
fun
)
{
if
(
pt_command
(
unit
,
cmd
,
0
,
fun
))
{
pt_req_sense
(
unit
,
0
);
static
void
pt_media_access_cmd
(
int
unit
,
int
tmo
,
char
*
cmd
,
char
*
fun
)
{
if
(
pt_command
(
unit
,
cmd
,
0
,
fun
))
{
pt_req_sense
(
unit
,
0
);
return
;
}
pi_disconnect
(
PI
);
pt_poll_dsc
(
unit
,
HZ
,
tmo
,
fun
);
pt_poll_dsc
(
unit
,
HZ
,
tmo
,
fun
);
}
static
void
pt_rewind
(
int
unit
)
{
char
rw_cmd
[
12
]
=
{
ATAPI_REWIND
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
void
pt_rewind
(
int
unit
)
{
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
)
{
char
wm_cmd
[
12
]
=
{
ATAPI_WFM
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
void
pt_write_fm
(
int
unit
)
{
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)
static
int
pt_reset
(
int
unit
)
{
int
i
,
k
,
flg
;
int
expect
[
5
]
=
{
1
,
1
,
1
,
0x14
,
0xeb
};
static
int
pt_reset
(
int
unit
)
{
int
i
,
k
,
flg
;
int
expect
[
5
]
=
{
1
,
1
,
1
,
0x14
,
0xeb
};
pi_connect
(
PI
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
7
,
8
);
write_reg
(
unit
,
6
,
DRIVE
);
write_reg
(
unit
,
7
,
8
);
pt_sleep
(
20
*
HZ
/
1000
);
pt_sleep
(
20
*
HZ
/
1000
);
k
=
0
;
while
((
k
++
<
PT_RESET_TMO
)
&&
(
status_reg
(
unit
)
&
STAT_BUSY
))
pt_sleep
(
HZ
/
10
);
k
=
0
;
while
((
k
++
<
PT_RESET_TMO
)
&&
(
status_reg
(
unit
)
&
STAT_BUSY
))
pt_sleep
(
HZ
/
10
);
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
)
{
printk
(
"%s: Reset (%d) signature = "
,
PT
.
name
,
k
);
for
(
i
=
0
;
i
<
5
;
i
++
)
printk
(
"%3x"
,
read_reg
(
unit
,
i
+
1
));
if
(
!
flg
)
printk
(
" (incorrect)"
);
printk
(
"%s: Reset (%d) signature = "
,
PT
.
name
,
k
);
for
(
i
=
0
;
i
<
5
;
i
++
)
printk
(
"%3x"
,
read_reg
(
unit
,
i
+
1
));
if
(
!
flg
)
printk
(
" (incorrect)"
);
printk
(
"
\n
"
);
}
pi_disconnect
(
PI
);
return
flg
-
1
;
return
flg
-
1
;
}
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
};
int
k
,
p
;
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
};
int
k
,
p
;
k
=
0
;
while
(
k
<
tmo
)
{
PT
.
last_sense
=
0
;
pt_atapi
(
unit
,
tr_cmd
,
0
,
NULL
,
DBMSG
(
"test unit ready"
));
p
=
PT
.
last_sense
;
if
(
!
p
)
return
0
;
if
(
!
(((
p
&
0xffff
)
==
0x0402
)
||
((
p
&
0xff
)
==
6
)))
return
p
;
k
++
;
pt_sleep
(
HZ
);
PT
.
last_sense
=
0
;
pt_atapi
(
unit
,
tr_cmd
,
0
,
NULL
,
DBMSG
(
"test unit ready"
));
p
=
PT
.
last_sense
;
if
(
!
p
)
return
0
;
if
(
!
(((
p
&
0xffff
)
==
0x0402
)
||
((
p
&
0xff
)
==
6
)))
return
p
;
k
++
;
pt_sleep
(
HZ
);
}
return
0x000020
;
/* timeout */
}
static
void
xs
(
char
*
buf
,
char
*
targ
,
int
offs
,
int
len
)
{
int
j
,
k
,
l
;
j
=
0
;
l
=
0
;
for
(
k
=
0
;
k
<
len
;
k
++
)
if
((
buf
[
k
+
offs
]
!=
0x20
)
||
(
buf
[
k
+
offs
]
!=
l
))
l
=
targ
[
j
++
]
=
buf
[
k
+
offs
];
if
(
l
==
0x20
)
j
--
;
targ
[
j
]
=
0
;
static
void
xs
(
char
*
buf
,
char
*
targ
,
int
offs
,
int
len
)
{
int
j
,
k
,
l
;
j
=
0
;
l
=
0
;
for
(
k
=
0
;
k
<
len
;
k
++
)
if
((
buf
[
k
+
offs
]
!=
0x20
)
||
(
buf
[
k
+
offs
]
!=
l
))
l
=
targ
[
j
++
]
=
buf
[
k
+
offs
];
if
(
l
==
0x20
)
j
--
;
targ
[
j
]
=
0
;
}
static
int
xn
(
char
*
buf
,
int
offs
,
int
size
)
{
int
v
,
k
;
static
int
xn
(
char
*
buf
,
int
offs
,
int
size
)
{
int
v
,
k
;
v
=
0
;
for
(
k
=
0
;
k
<
size
;
k
++
)
v
=
v
*
256
+
(
buf
[
k
+
offs
]
&
0xff
);
v
=
0
;
for
(
k
=
0
;
k
<
size
;
k
++
)
v
=
v
*
256
+
(
buf
[
k
+
offs
]
&
0xff
);
return
v
;
}
static
int
pt_identify
(
int
unit
)
{
int
dt
,
s
;
char
*
ms
[
2
]
=
{
"master"
,
"slave"
};
char
mf
[
10
],
id
[
18
];
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
ls_cmd
[
12
]
=
{
ATAPI_LOG_SENSE
,
0
,
0x71
,
0
,
0
,
0
,
0
,
0
,
36
,
0
,
0
,
0
};
char
buf
[
36
];
s
=
pt_atapi
(
unit
,
id_cmd
,
36
,
buf
,
"identify"
);
if
(
s
)
return
-
1
;
static
int
pt_identify
(
int
unit
)
{
int
dt
,
s
;
char
*
ms
[
2
]
=
{
"master"
,
"slave"
};
char
mf
[
10
],
id
[
18
];
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
ls_cmd
[
12
]
=
{
ATAPI_LOG_SENSE
,
0
,
0x71
,
0
,
0
,
0
,
0
,
0
,
36
,
0
,
0
,
0
};
char
buf
[
36
];
s
=
pt_atapi
(
unit
,
id_cmd
,
36
,
buf
,
"identify"
);
if
(
s
)
return
-
1
;
dt
=
buf
[
0
]
&
0x1f
;
if
(
dt
!=
1
)
{
if
(
verbose
)
printk
(
"%s: Drive %d, unsupported type %d
\n
"
,
PT
.
name
,
PT
.
drive
,
dt
);
return
-
1
;
}
if
(
verbose
)
printk
(
"%s: Drive %d, unsupported type %d
\n
"
,
PT
.
name
,
PT
.
drive
,
dt
);
return
-
1
;
}
xs
(
buf
,
mf
,
8
,
8
);
xs
(
buf
,
id
,
16
,
16
);
xs
(
buf
,
mf
,
8
,
8
);
xs
(
buf
,
id
,
16
,
16
);
PT
.
flags
=
0
;
PT
.
capacity
=
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
(
!
(
buf
[
2
]
&
0x80
))
PT
.
flags
|=
PT_WRITE_OK
;
PT
.
bs
=
xn
(
buf
,
10
,
2
);
if
(
!
pt_atapi
(
unit
,
ms_cmd
,
36
,
buf
,
"mode sense"
))
{
if
(
!
(
buf
[
2
]
&
0x80
))
PT
.
flags
|=
PT_WRITE_OK
;
PT
.
bs
=
xn
(
buf
,
10
,
2
);
}
if
(
!
pt_atapi
(
unit
,
ls_cmd
,
36
,
buf
,
"log sense"
))
PT
.
capacity
=
xn
(
buf
,
24
,
4
);
if
(
!
pt_atapi
(
unit
,
ls_cmd
,
36
,
buf
,
"log sense"
))
PT
.
capacity
=
xn
(
buf
,
24
,
4
);
printk
(
"%s: %s %s, %s"
,
PT
.
name
,
mf
,
id
,
ms
[
PT
.
drive
]);
if
(
!
(
PT
.
flags
&
PT_MEDIA
))
printk
(
", no media
\n
"
);
else
{
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
printk
(
", RO"
);
printk
(
", blocksize %d, %d MB
\n
"
,
PT
.
bs
,
PT
.
capacity
/
1024
);
}
printk
(
"%s: %s %s, %s"
,
PT
.
name
,
mf
,
id
,
ms
[
PT
.
drive
]);
if
(
!
(
PT
.
flags
&
PT_MEDIA
))
printk
(
", no media
\n
"
);
else
{
if
(
!
(
PT
.
flags
&
PT_WRITE_OK
))
printk
(
", RO"
);
printk
(
", blocksize %d, %d MB
\n
"
,
PT
.
bs
,
PT
.
capacity
/
1024
);
}
return
0
;
}
static
int
pt_probe
(
int
unit
)
/* returns 0, with id set if drive is detected
-1, if drive detection failed
*/
{
if
(
PT
.
drive
==
-
1
)
{
for
(
PT
.
drive
=
0
;
PT
.
drive
<=
1
;
PT
.
drive
++
)
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
/*
* returns 0, with id set if drive is detected
* -1, if drive detection failed
*/
static
int
pt_probe
(
int
unit
)
{
if
(
PT
.
drive
==
-
1
)
{
for
(
PT
.
drive
=
0
;
PT
.
drive
<=
1
;
PT
.
drive
++
)
if
(
!
pt_reset
(
unit
))
return
pt_identify
(
unit
);
}
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
)
{
int
k
,
unit
;
static
int
pt_detect
(
void
)
{
int
k
,
unit
;
printk
(
"%s: %s version %s, major %d
\n
"
,
name
,
name
,
PT_VERSION
,
major
);
printk
(
"%s: %s version %s, major %d
\n
"
,
name
,
name
,
PT_VERSION
,
major
);
k
=
0
;
if
(
pt_drive_count
==
0
)
{
unit
=
0
;
if
(
pi_init
(
PI
,
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
pt_scratch
,
PI_PT
,
verbose
,
PT
.
name
))
{
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
k
++
;
}
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
],
DU
[
D_PRO
],
DU
[
D_DLY
],
pt_scratch
,
PI_PT
,
verbose
,
PT
.
name
))
{
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
k
++
;
}
else
pi_release
(
PI
);
}
if
(
k
)
return
0
;
printk
(
"%s: No ATAPI tape drive detected
\n
"
,
name
);
unit
=
0
;
if
(
pi_init
(
PI
,
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
pt_scratch
,
PI_PT
,
verbose
,
PT
.
name
))
{
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
k
++
;
}
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
],
DU
[
D_PRO
],
DU
[
D_DLY
],
pt_scratch
,
PI_PT
,
verbose
,
PT
.
name
))
{
if
(
!
pt_probe
(
unit
))
{
PT
.
present
=
1
;
k
++
;
}
else
pi_release
(
PI
);
}
if
(
k
)
return
0
;
printk
(
"%s: No ATAPI tape drive detected
\n
"
,
name
);
return
-
1
;
}
#define DEVICE_NR(dev) (minor(dev) & 0x7F)
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
static
int
pt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
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
)
)
{
atomic_inc
(
&
PT
.
available
);
if
(
!
atomic_dec_and_test
(
&
PT
.
available
)
)
{
atomic_inc
(
&
PT
.
available
);
return
-
EBUSY
;
}
pt_identify
(
unit
);
if
(
!
PT
.
flags
&
PT_MEDIA
)
{
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
-
ENODEV
;
}
}
if
((
!
PT
.
flags
&
PT_WRITE_OK
)
&&
(
file
->
f_mode
&
2
))
{
atomic_inc
(
&
PT
.
available
);
if
((
!
PT
.
flags
&
PT_WRITE_OK
)
&&
(
file
->
f_mode
&
2
))
{
atomic_inc
(
&
PT
.
available
);
return
-
EROFS
;
}
}
if
(
!
(
minor
(
inode
->
i_rdev
)
&
128
))
PT
.
flags
|=
PT_REWIND
;
PT
.
bufptr
=
kmalloc
(
PT_BUFSIZE
,
GFP_KERNEL
);
PT
.
bufptr
=
kmalloc
(
PT_BUFSIZE
,
GFP_KERNEL
);
if
(
PT
.
bufptr
==
NULL
)
{
atomic_inc
(
&
PT
.
available
);
printk
(
"%s: buffer allocation failed
\n
"
,
PT
.
name
);
atomic_inc
(
&
PT
.
available
);
printk
(
"%s: buffer allocation failed
\n
"
,
PT
.
name
);
return
-
ENOMEM
;
}
return
0
;
return
0
;
}
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
int
pt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
unit
;
struct
mtop
mtop
;
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
if
(
unit
>=
PT_UNITS
)
unit
=
DEVICE_NR
(
inode
->
i_rdev
);
if
(
unit
>=
PT_UNITS
)
return
-
EINVAL
;
if
(
!
PT
.
present
)
if
(
!
PT
.
present
)
return
-
ENODEV
;
switch
(
cmd
)
{
case
MTIOCTOP
:
if
(
copy_from_user
((
char
*
)
&
mtop
,
(
char
*
)
arg
,
sizeof
(
struct
mtop
)))
return
-
EFAULT
;
switch
(
cmd
)
{
case
MTIOCTOP
:
if
(
copy_from_user
((
char
*
)
&
mtop
,
(
char
*
)
arg
,
sizeof
(
struct
mtop
)))
return
-
EFAULT
;
switch
(
mtop
.
mt_op
)
{
case
MTREW
:
case
MTREW
:
pt_rewind
(
unit
);
return
0
;
case
MTWEOF
:
case
MTWEOF
:
pt_write_fm
(
unit
);
return
0
;
default:
printk
(
"%s: Unimplemented mt_op %d
\n
"
,
PT
.
name
,
mtop
.
mt_op
);
default:
printk
(
"%s: Unimplemented mt_op %d
\n
"
,
PT
.
name
,
mtop
.
mt_op
);
return
-
EINVAL
;
}
default:
printk
(
"%s: Unimplemented ioctl 0x%x
\n
"
,
PT
.
name
,
cmd
);
return
-
EINVAL
;
default:
printk
(
"%s: Unimplemented ioctl 0x%x
\n
"
,
PT
.
name
,
cmd
);
return
-
EINVAL
;
}
}
}
static
int
pt_release
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
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
))
return
-
EINVAL
;
if
((
unit
>=
PT_UNITS
)
||
(
atomic_read
(
&
PT
.
available
)
>
1
))
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
);
PT
.
bufptr
=
NULL
;
atomic_inc
(
&
PT
.
available
);
atomic_inc
(
&
PT
.
available
);
return
0
;
}
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
pt_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
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
};
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
PT
.
flags
|=
PT_READING
;
if
(
pt_atapi
(
unit
,
rd_cmd
,
0
,
NULL
,
"start read-ahead"
))
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
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
};
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
PT
.
flags
|=
PT_READING
;
if
(
pt_atapi
(
unit
,
rd_cmd
,
0
,
NULL
,
"start read-ahead"
))
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
;
while
(
count
>
0
)
{
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
)
{
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"read"
))
return
-
EIO
;
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
DBMSG
(
"read DRQ"
),
""
);
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 */
if
(
r
&
STAT_SENSE
)
{
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
rd_cmd
[
4
]
=
b
;
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
));
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
(
1
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
DBMSG
(
"read DRQ"
),
""
);
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
;
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
;
}
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
return
t
;
}
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
pt_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
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
};
int
k
,
n
,
r
,
p
,
s
,
t
,
b
;
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
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
};
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
)))
{
PT
.
flags
|=
PT_WRITING
;
if
(
pt_atapi
(
unit
,
wr_cmd
,
0
,
NULL
,
"start buffer-available mode"
))
return
-
EIO
;
}
else
if
(
PT
.
flags
&
PT_READING
)
return
-
EIO
;
if
(
!
(
PT
.
flags
&
(
PT_READING
|
PT_WRITING
)))
{
PT
.
flags
|=
PT_WRITING
;
if
(
pt_atapi
(
unit
,
wr_cmd
,
0
,
NULL
,
"start buffer-available mode"
))
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
;
while
(
count
>
0
)
{
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
)
{
if
(
!
pt_poll_dsc
(
unit
,
HZ
/
100
,
PT_TMO
,
"write"
))
return
-
EIO
;
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
DBMSG
(
"write DRQ"
),
NULL
);
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 */
if
(
r
&
STAT_SENSE
)
{
pi_disconnect
(
PI
);
pt_req_sense
(
unit
,
0
);
return
-
EIO
;
}
wr_cmd
[
4
]
=
b
;
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
));
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
(
1
)
{
r
=
pt_wait
(
unit
,
STAT_BUSY
,
STAT_DRQ
|
STAT_ERR
|
STAT_READY
,
DBMSG
(
"write DRQ"
),
NULL
);
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
;
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
;
}
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
pi_disconnect
(
PI
);
if
(
PT
.
flags
&
PT_EOF
)
break
;
}
return
t
;
...
...
@@ -915,23 +982,23 @@ static int __init pt_init(void)
if
(
pt_detect
())
return
-
1
;
if
(
register_chrdev
(
major
,
name
,
&
pt_fops
))
{
printk
(
"pt_init: unable to get major number %d
\n
"
,
major
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
pi_release
(
PI
);
if
(
register_chrdev
(
major
,
name
,
&
pt_fops
))
{
printk
(
"pt_init: unable to get major number %d
\n
"
,
major
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
pi_release
(
PI
);
return
-
1
;
}
devfs_mk_dir
(
"pt"
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
devfs_mk_dir
(
"pt"
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
{
devfs_mk_cdev
(
MKDEV
(
major
,
unit
),
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%d"
,
unit
);
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%d"
,
unit
);
devfs_mk_cdev
(
MKDEV
(
major
,
unit
+
128
),
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%dn"
,
unit
);
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"pt/%dn"
,
unit
);
}
return
0
;
}
...
...
@@ -939,14 +1006,14 @@ static int __init pt_init(void)
static
void
__exit
pt_exit
(
void
)
{
int
unit
;
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
{
devfs_remove
(
"pt/%d"
,
unit
);
devfs_remove
(
"pt/%dn"
,
unit
);
}
devfs_remove
(
"pt"
);
unregister_chrdev
(
major
,
name
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
unregister_chrdev
(
major
,
name
);
for
(
unit
=
0
;
unit
<
PT_UNITS
;
unit
++
)
if
(
PT
.
present
)
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