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
a034f8d6
Commit
a034f8d6
authored
Oct 19, 2004
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge pobox.com:/spare/repo/libata-dev/atapi
into pobox.com:/spare/repo/libata-2.6
parents
e2e875d9
afa386d7
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
177 additions
and
43 deletions
+177
-43
drivers/scsi/libata-core.c
drivers/scsi/libata-core.c
+163
-41
drivers/scsi/libata-scsi.c
drivers/scsi/libata-scsi.c
+10
-2
include/linux/libata.h
include/linux/libata.h
+4
-0
No files found.
drivers/scsi/libata-core.c
View file @
a034f8d6
...
...
@@ -39,6 +39,7 @@
#include <linux/workqueue.h>
#include <scsi/scsi.h>
#include "scsi.h"
#include "scsi_priv.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <asm/io.h>
...
...
@@ -58,6 +59,7 @@ static int ata_choose_xfer_mode(struct ata_port *ap,
u8
*
xfer_mode_out
,
unsigned
int
*
xfer_shift_out
);
static
int
ata_qc_complete_noop
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
);
static
void
__ata_qc_complete
(
struct
ata_queued_cmd
*
qc
);
static
unsigned
int
ata_unique_id
=
1
;
static
struct
workqueue_struct
*
ata_wq
;
...
...
@@ -2193,11 +2195,50 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
kunmap
(
page
);
}
static
void
atapi_pio_sector
(
struct
ata_queued_cmd
*
qc
)
static
void
__atapi_pio_bytes
(
struct
ata_queued_cmd
*
qc
,
unsigned
int
bytes
)
{
int
do_write
=
(
qc
->
tf
.
flags
&
ATA_TFLAG_WRITE
);
struct
scatterlist
*
sg
=
qc
->
sg
;
struct
ata_port
*
ap
=
qc
->
ap
;
struct
page
*
page
;
unsigned
char
*
buf
;
unsigned
int
count
;
if
(
qc
->
curbytes
==
qc
->
nbytes
-
bytes
)
ap
->
pio_task_state
=
PIO_ST_LAST
;
next_sg:
sg
=
&
qc
->
sg
[
qc
->
cursg
];
page
=
sg
->
page
;
count
=
min
(
sg_dma_len
(
sg
)
-
qc
->
cursg_ofs
,
bytes
);
buf
=
kmap
(
page
)
+
sg
->
offset
+
qc
->
cursg_ofs
;
bytes
-=
count
;
qc
->
curbytes
+=
count
;
qc
->
cursg_ofs
+=
count
;
if
(
qc
->
cursg_ofs
==
sg_dma_len
(
sg
))
{
qc
->
cursg
++
;
qc
->
cursg_ofs
=
0
;
}
DPRINTK
(
"data %s
\n
"
,
qc
->
tf
.
flags
&
ATA_TFLAG_WRITE
?
"write"
:
"read"
);
/* do the actual data transfer */
ata_data_xfer
(
ap
,
buf
,
count
,
do_write
);
kunmap
(
page
);
if
(
bytes
)
goto
next_sg
;
}
static
void
atapi_pio_bytes
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_device
*
dev
=
qc
->
dev
;
unsigned
int
i
,
i
reason
,
bc_lo
,
bc_hi
,
bytes
;
unsigned
int
ireason
,
bc_lo
,
bc_hi
,
bytes
;
int
i_write
,
do_write
=
(
qc
->
tf
.
flags
&
ATA_TFLAG_WRITE
)
?
1
:
0
;
ap
->
ops
->
tf_read
(
ap
,
&
qc
->
tf
);
...
...
@@ -2215,16 +2256,7 @@ static void atapi_pio_sector(struct ata_queued_cmd *qc)
if
(
do_write
!=
i_write
)
goto
err_out
;
/* make sure byte count is multiple of sector size; not
* required by standard (warning! warning!), but IDE driver
* does this to simplify things a bit. We are lazy, and
* follow suit.
*/
if
(
bytes
&
(
ATA_SECT_SIZE
-
1
))
goto
err_out
;
for
(
i
=
0
;
i
<
(
bytes
>>
9
);
i
++
)
ata_pio_sector
(
qc
);
__atapi_pio_bytes
(
qc
,
bytes
);
return
;
...
...
@@ -2265,19 +2297,30 @@ static void ata_pio_block(struct ata_port *ap)
}
}
qc
=
ata_qc_from_tag
(
ap
,
ap
->
active_tag
);
assert
(
qc
!=
NULL
);
if
(
is_atapi_taskfile
(
&
qc
->
tf
))
{
/* no more data to transfer or unsupported ATAPI command */
if
((
status
&
ATA_DRQ
)
==
0
)
{
ap
->
pio_task_state
=
PIO_ST_IDLE
;
ata_irq_on
(
ap
);
ata_qc_complete
(
qc
,
status
);
return
;
}
atapi_pio_bytes
(
qc
);
}
else
{
/* handle BSY=0, DRQ=0 as error */
if
((
status
&
ATA_DRQ
)
==
0
)
{
ap
->
pio_task_state
=
PIO_ST_ERR
;
return
;
}
qc
=
ata_qc_from_tag
(
ap
,
ap
->
active_tag
);
assert
(
qc
!=
NULL
);
if
(
is_atapi_taskfile
(
&
qc
->
tf
))
atapi_pio_sector
(
qc
);
else
ata_pio_sector
(
qc
);
}
}
static
void
ata_pio_error
(
struct
ata_port
*
ap
)
...
...
@@ -2335,6 +2378,59 @@ static void ata_pio_task(void *_data)
}
}
static
void
atapi_request_sense
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
,
struct
scsi_cmnd
*
cmd
)
{
DECLARE_COMPLETION
(
wait
);
struct
ata_queued_cmd
*
qc
;
unsigned
long
flags
;
int
using_pio
=
dev
->
flags
&
ATA_DFLAG_PIO
;
int
rc
;
DPRINTK
(
"ATAPI request sense
\n
"
);
qc
=
ata_qc_new_init
(
ap
,
dev
);
BUG_ON
(
qc
==
NULL
);
/* FIXME: is this needed? */
memset
(
cmd
->
sense_buffer
,
0
,
sizeof
(
cmd
->
sense_buffer
));
ata_sg_init_one
(
qc
,
cmd
->
sense_buffer
,
sizeof
(
cmd
->
sense_buffer
));
qc
->
pci_dma_dir
=
PCI_DMA_FROMDEVICE
;
memset
(
&
qc
->
cdb
,
0
,
sizeof
(
ap
->
cdb_len
));
qc
->
cdb
[
0
]
=
REQUEST_SENSE
;
qc
->
cdb
[
4
]
=
SCSI_SENSE_BUFFERSIZE
;
qc
->
tf
.
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
qc
->
tf
.
command
=
ATA_CMD_PACKET
;
if
(
using_pio
)
{
qc
->
tf
.
protocol
=
ATA_PROT_ATAPI
;
qc
->
tf
.
lbam
=
(
8
*
1024
)
&
0xff
;
qc
->
tf
.
lbah
=
(
8
*
1024
)
>>
8
;
qc
->
nbytes
=
SCSI_SENSE_BUFFERSIZE
;
}
else
{
qc
->
tf
.
protocol
=
ATA_PROT_ATAPI_DMA
;
qc
->
tf
.
feature
|=
ATAPI_PKT_DMA
;
}
qc
->
waiting
=
&
wait
;
qc
->
complete_fn
=
ata_qc_complete_noop
;
spin_lock_irqsave
(
&
ap
->
host_set
->
lock
,
flags
);
rc
=
ata_qc_issue
(
qc
);
spin_unlock_irqrestore
(
&
ap
->
host_set
->
lock
,
flags
);
if
(
rc
)
ata_port_disable
(
ap
);
else
wait_for_completion
(
&
wait
);
DPRINTK
(
"EXIT
\n
"
);
}
/**
* ata_qc_timeout - Handle timeout of queued command
* @qc: Command that timed out
...
...
@@ -2356,10 +2452,29 @@ static void ata_pio_task(void *_data)
static
void
ata_qc_timeout
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_device
*
dev
=
qc
->
dev
;
u8
host_stat
=
0
,
drv_stat
;
DPRINTK
(
"ENTER
\n
"
);
/* FIXME: doesn't this conflict with timeout handling? */
if
(
qc
->
dev
->
class
==
ATA_DEV_ATAPI
&&
qc
->
scsicmd
)
{
struct
scsi_cmnd
*
cmd
=
qc
->
scsicmd
;
if
(
!
scsi_eh_eflags_chk
(
cmd
,
SCSI_EH_CANCEL_CMD
))
{
/* finish completing original command */
__ata_qc_complete
(
qc
);
atapi_request_sense
(
ap
,
dev
,
cmd
);
cmd
->
result
=
(
CHECK_CONDITION
<<
1
)
|
(
DID_OK
<<
16
);
scsi_finish_command
(
cmd
);
goto
out
;
}
}
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
...
...
@@ -2393,7 +2508,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
ata_qc_complete
(
qc
,
drv_stat
);
break
;
}
out:
DPRINTK
(
"EXIT
\n
"
);
}
...
...
@@ -2482,6 +2597,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
qc
->
dev
=
dev
;
qc
->
cursect
=
qc
->
cursg
=
qc
->
cursg_ofs
=
0
;
qc
->
nsect
=
0
;
qc
->
nbytes
=
qc
->
curbytes
=
0
;
ata_tf_init
(
ap
,
&
qc
->
tf
,
dev
->
devno
);
...
...
@@ -2497,6 +2613,30 @@ static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
return
0
;
}
static
void
__ata_qc_complete
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
unsigned
int
tag
,
do_clear
=
0
;
qc
->
flags
=
0
;
tag
=
qc
->
tag
;
if
(
likely
(
ata_tag_valid
(
tag
)))
{
if
(
tag
==
ap
->
active_tag
)
ap
->
active_tag
=
ATA_TAG_POISON
;
qc
->
tag
=
ATA_TAG_POISON
;
do_clear
=
1
;
}
if
(
qc
->
waiting
)
{
struct
completion
*
waiting
=
qc
->
waiting
;
qc
->
waiting
=
NULL
;
complete
(
waiting
);
}
if
(
likely
(
do_clear
))
clear_bit
(
tag
,
&
ap
->
qactive
);
}
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
...
...
@@ -2508,8 +2648,6 @@ static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
void
ata_qc_complete
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
unsigned
int
tag
,
do_clear
=
0
;
int
rc
;
assert
(
qc
!=
NULL
);
/* ata_qc_from_tag _might_ return NULL */
...
...
@@ -2527,23 +2665,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if
(
rc
!=
0
)
return
;
qc
->
flags
=
0
;
tag
=
qc
->
tag
;
if
(
likely
(
ata_tag_valid
(
tag
)))
{
if
(
tag
==
ap
->
active_tag
)
ap
->
active_tag
=
ATA_TAG_POISON
;
qc
->
tag
=
ATA_TAG_POISON
;
do_clear
=
1
;
}
if
(
qc
->
waiting
)
{
struct
completion
*
waiting
=
qc
->
waiting
;
qc
->
waiting
=
NULL
;
complete
(
waiting
);
}
if
(
likely
(
do_clear
))
clear_bit
(
tag
,
&
ap
->
qactive
);
__ata_qc_complete
(
qc
);
VPRINTK
(
"EXIT
\n
"
);
}
...
...
drivers/scsi/libata-scsi.c
View file @
a034f8d6
...
...
@@ -1248,9 +1248,15 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
{
struct
scsi_cmnd
*
cmd
=
qc
->
scsicmd
;
if
(
unlikely
(
drv_stat
&
(
ATA_ERR
|
ATA_BUSY
|
ATA_DRQ
)))
if
(
unlikely
(
drv_stat
&
(
ATA_ERR
|
ATA_BUSY
|
ATA_DRQ
)))
{
DPRINTK
(
"request check condition
\n
"
);
cmd
->
result
=
SAM_STAT_CHECK_CONDITION
;
else
{
qc
->
scsidone
(
cmd
);
return
1
;
}
else
{
u8
*
scsicmd
=
cmd
->
cmnd
;
if
(
scsicmd
[
0
]
==
INQUIRY
)
{
...
...
@@ -1322,6 +1328,8 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
#endif
}
qc
->
nbytes
=
cmd
->
bufflen
;
return
0
;
}
...
...
include/linux/libata.h
View file @
a034f8d6
...
...
@@ -230,6 +230,10 @@ struct ata_queued_cmd {
unsigned
int
nsect
;
unsigned
int
cursect
;
unsigned
int
nbytes
;
unsigned
int
curbytes
;
unsigned
int
cursg
;
unsigned
int
cursg_ofs
;
...
...
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