Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
8bf62ece
L
linux
项目概览
xiphi1978
/
linux
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8bf62ece
编写于
5月 12, 2005
作者:
A
Albert Lee
提交者:
Jeff Garzik
5月 12, 2005
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[libata] C/H/S support, for older devices
上级
88d7bd8c
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
312 addition
and
128 deletion
+312
-128
drivers/scsi/libata-core.c
drivers/scsi/libata-core.c
+115
-25
drivers/scsi/libata-scsi.c
drivers/scsi/libata-scsi.c
+177
-103
include/linux/ata.h
include/linux/ata.h
+14
-0
include/linux/libata.h
include/linux/libata.h
+6
-0
未找到文件。
drivers/scsi/libata-core.c
浏览文件 @
8bf62ece
...
@@ -52,6 +52,7 @@
...
@@ -52,6 +52,7 @@
static
unsigned
int
ata_busy_sleep
(
struct
ata_port
*
ap
,
static
unsigned
int
ata_busy_sleep
(
struct
ata_port
*
ap
,
unsigned
long
tmout_pat
,
unsigned
long
tmout_pat
,
unsigned
long
tmout
);
unsigned
long
tmout
);
static
void
ata_dev_init_params
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
);
static
void
ata_set_mode
(
struct
ata_port
*
ap
);
static
void
ata_set_mode
(
struct
ata_port
*
ap
);
static
void
ata_dev_set_xfermode
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
);
static
void
ata_dev_set_xfermode
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
);
static
unsigned
int
ata_get_mode_mask
(
struct
ata_port
*
ap
,
int
shift
);
static
unsigned
int
ata_get_mode_mask
(
struct
ata_port
*
ap
,
int
shift
);
...
@@ -1008,7 +1009,7 @@ static inline void ata_dump_id(struct ata_device *dev)
...
@@ -1008,7 +1009,7 @@ static inline void ata_dump_id(struct ata_device *dev)
static
void
ata_dev_identify
(
struct
ata_port
*
ap
,
unsigned
int
device
)
static
void
ata_dev_identify
(
struct
ata_port
*
ap
,
unsigned
int
device
)
{
{
struct
ata_device
*
dev
=
&
ap
->
device
[
device
];
struct
ata_device
*
dev
=
&
ap
->
device
[
device
];
unsigned
int
i
;
unsigned
int
major_version
;
u16
tmp
;
u16
tmp
;
unsigned
long
xfer_modes
;
unsigned
long
xfer_modes
;
u8
status
;
u8
status
;
...
@@ -1106,9 +1107,9 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
...
@@ -1106,9 +1107,9 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
* common ATA, ATAPI feature tests
* common ATA, ATAPI feature tests
*/
*/
/* we require
LBA and DMA support (bits 8 & 9
of word 49) */
/* we require
DMA support (bits 8
of word 49) */
if
(
!
ata_id_has_dma
(
dev
->
id
)
||
!
ata_id_has_lba
(
dev
->
id
)
)
{
if
(
!
ata_id_has_dma
(
dev
->
id
))
{
printk
(
KERN_DEBUG
"ata%u: no dma
/lba
\n
"
,
ap
->
id
);
printk
(
KERN_DEBUG
"ata%u: no dma
\n
"
,
ap
->
id
);
goto
err_out_nosup
;
goto
err_out_nosup
;
}
}
...
@@ -1128,32 +1129,69 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
...
@@ -1128,32 +1129,69 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
if
(
!
ata_id_is_ata
(
dev
->
id
))
/* sanity check */
if
(
!
ata_id_is_ata
(
dev
->
id
))
/* sanity check */
goto
err_out_nosup
;
goto
err_out_nosup
;
/* get major version */
tmp
=
dev
->
id
[
ATA_ID_MAJOR_VER
];
tmp
=
dev
->
id
[
ATA_ID_MAJOR_VER
];
for
(
i
=
14
;
i
>=
1
;
i
--
)
for
(
major_version
=
14
;
major_version
>=
1
;
major_version
--
)
if
(
tmp
&
(
1
<<
i
))
if
(
tmp
&
(
1
<<
major_version
))
break
;
break
;
/* we require at least ATA-3 */
/*
if
(
i
<
3
)
{
* The exact sequence expected by certain pre-ATA4 drives is:
printk
(
KERN_DEBUG
"ata%u: no ATA-3
\n
"
,
ap
->
id
);
* SRST RESET
goto
err_out_nosup
;
* IDENTIFY
}
* INITIALIZE DEVICE PARAMETERS
* anything else..
* Some drives were very specific about that exact sequence.
*/
if
(
major_version
<
4
||
(
!
ata_id_has_lba
(
dev
->
id
)))
ata_dev_init_params
(
ap
,
dev
);
if
(
ata_id_has_lba
(
dev
->
id
))
{
dev
->
flags
|=
ATA_DFLAG_LBA
;
if
(
ata_id_has_lba48
(
dev
->
id
))
{
dev
->
flags
|=
ATA_DFLAG_LBA48
;
dev
->
n_sectors
=
ata_id_u64
(
dev
->
id
,
100
);
}
else
{
dev
->
n_sectors
=
ata_id_u32
(
dev
->
id
,
60
);
}
/* print device info to dmesg */
printk
(
KERN_INFO
"ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s
\n
"
,
ap
->
id
,
device
,
major_version
,
ata_mode_string
(
xfer_modes
),
(
unsigned
long
long
)
dev
->
n_sectors
,
dev
->
flags
&
ATA_DFLAG_LBA48
?
" LBA48"
:
" LBA"
);
}
else
{
/* CHS */
/* Default translation */
dev
->
cylinders
=
dev
->
id
[
1
];
dev
->
heads
=
dev
->
id
[
3
];
dev
->
sectors
=
dev
->
id
[
6
];
dev
->
n_sectors
=
dev
->
cylinders
*
dev
->
heads
*
dev
->
sectors
;
if
(
ata_id_current_chs_valid
(
dev
->
id
))
{
/* Current CHS translation is valid. */
dev
->
cylinders
=
dev
->
id
[
54
];
dev
->
heads
=
dev
->
id
[
55
];
dev
->
sectors
=
dev
->
id
[
56
];
dev
->
n_sectors
=
ata_id_u32
(
dev
->
id
,
57
);
}
/* print device info to dmesg */
printk
(
KERN_INFO
"ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d
\n
"
,
ap
->
id
,
device
,
major_version
,
ata_mode_string
(
xfer_modes
),
(
unsigned
long
long
)
dev
->
n_sectors
,
(
int
)
dev
->
cylinders
,
(
int
)
dev
->
heads
,
(
int
)
dev
->
sectors
);
if
(
ata_id_has_lba48
(
dev
->
id
))
{
dev
->
flags
|=
ATA_DFLAG_LBA48
;
dev
->
n_sectors
=
ata_id_u64
(
dev
->
id
,
100
);
}
else
{
dev
->
n_sectors
=
ata_id_u32
(
dev
->
id
,
60
);
}
}
ap
->
host
->
max_cmd_len
=
16
;
ap
->
host
->
max_cmd_len
=
16
;
/* print device info to dmesg */
printk
(
KERN_INFO
"ata%u: dev %u ATA, max %s, %Lu sectors:%s
\n
"
,
ap
->
id
,
device
,
ata_mode_string
(
xfer_modes
),
(
unsigned
long
long
)
dev
->
n_sectors
,
dev
->
flags
&
ATA_DFLAG_LBA48
?
" lba48"
:
""
);
}
}
/* ATAPI-specific feature tests */
/* ATAPI-specific feature tests */
...
@@ -1946,6 +1984,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
...
@@ -1946,6 +1984,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
DPRINTK
(
"EXIT
\n
"
);
DPRINTK
(
"EXIT
\n
"
);
}
}
/**
* ata_dev_init_params - Issue INIT DEV PARAMS command
* @ap: Port associated with device @dev
* @dev: Device to which command will be sent
*
* LOCKING:
*/
static
void
ata_dev_init_params
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
)
{
DECLARE_COMPLETION
(
wait
);
struct
ata_queued_cmd
*
qc
;
int
rc
;
unsigned
long
flags
;
u16
sectors
=
dev
->
id
[
6
];
u16
heads
=
dev
->
id
[
3
];
/* Number of sectors per track 1-255. Number of heads 1-16 */
if
(
sectors
<
1
||
sectors
>
255
||
heads
<
1
||
heads
>
16
)
return
;
/* set up init dev params taskfile */
DPRINTK
(
"init dev params
\n
"
);
qc
=
ata_qc_new_init
(
ap
,
dev
);
BUG_ON
(
qc
==
NULL
);
qc
->
tf
.
command
=
ATA_CMD_INIT_DEV_PARAMS
;
qc
->
tf
.
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
qc
->
tf
.
protocol
=
ATA_PROT_NODATA
;
qc
->
tf
.
nsect
=
sectors
;
qc
->
tf
.
device
|=
(
heads
-
1
)
&
0x0f
;
/* max head = num. of heads - 1 */
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_sg_clean -
* ata_sg_clean -
* @qc:
* @qc:
...
@@ -2736,8 +2822,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
...
@@ -2736,8 +2822,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
ata_tf_init
(
ap
,
&
qc
->
tf
,
dev
->
devno
);
ata_tf_init
(
ap
,
&
qc
->
tf
,
dev
->
devno
);
if
(
dev
->
flags
&
ATA_DFLAG_LBA48
)
if
(
dev
->
flags
&
ATA_DFLAG_LBA
)
{
qc
->
tf
.
flags
|=
ATA_TFLAG_LBA48
;
qc
->
tf
.
flags
|=
ATA_TFLAG_LBA
;
if
(
dev
->
flags
&
ATA_DFLAG_LBA48
)
qc
->
tf
.
flags
|=
ATA_TFLAG_LBA48
;
}
}
}
return
qc
;
return
qc
;
...
...
drivers/scsi/libata-scsi.c
浏览文件 @
8bf62ece
...
@@ -435,77 +435,107 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
...
@@ -435,77 +435,107 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
static
unsigned
int
ata_scsi_verify_xlat
(
struct
ata_queued_cmd
*
qc
,
u8
*
scsicmd
)
static
unsigned
int
ata_scsi_verify_xlat
(
struct
ata_queued_cmd
*
qc
,
u8
*
scsicmd
)
{
{
struct
ata_taskfile
*
tf
=
&
qc
->
tf
;
struct
ata_taskfile
*
tf
=
&
qc
->
tf
;
struct
ata_device
*
dev
=
qc
->
dev
;
unsigned
int
lba
=
tf
->
flags
&
ATA_TFLAG_LBA
;
unsigned
int
lba48
=
tf
->
flags
&
ATA_TFLAG_LBA48
;
unsigned
int
lba48
=
tf
->
flags
&
ATA_TFLAG_LBA48
;
u64
dev_sectors
=
qc
->
dev
->
n_sectors
;
u64
dev_sectors
=
qc
->
dev
->
n_sectors
;
u64
sect
=
0
;
u64
block
=
0
;
u32
n_
sect
=
0
;
u32
n_
block
=
0
;
tf
->
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
tf
->
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
tf
->
protocol
=
ATA_PROT_NODATA
;
tf
->
protocol
=
ATA_PROT_NODATA
;
tf
->
device
|=
ATA_LBA
;
if
(
scsicmd
[
0
]
==
VERIFY
)
{
if
(
scsicmd
[
0
]
==
VERIFY
)
{
sect
|=
((
u64
)
scsicmd
[
2
])
<<
24
;
block
|=
((
u64
)
scsicmd
[
2
])
<<
24
;
sect
|=
((
u64
)
scsicmd
[
3
])
<<
16
;
block
|=
((
u64
)
scsicmd
[
3
])
<<
16
;
sect
|=
((
u64
)
scsicmd
[
4
])
<<
8
;
block
|=
((
u64
)
scsicmd
[
4
])
<<
8
;
sect
|=
((
u64
)
scsicmd
[
5
]);
block
|=
((
u64
)
scsicmd
[
5
]);
n_
sect
|=
((
u32
)
scsicmd
[
7
])
<<
8
;
n_
block
|=
((
u32
)
scsicmd
[
7
])
<<
8
;
n_
sect
|=
((
u32
)
scsicmd
[
8
]);
n_
block
|=
((
u32
)
scsicmd
[
8
]);
}
}
else
if
(
scsicmd
[
0
]
==
VERIFY_16
)
{
else
if
(
scsicmd
[
0
]
==
VERIFY_16
)
{
sect
|=
((
u64
)
scsicmd
[
2
])
<<
56
;
block
|=
((
u64
)
scsicmd
[
2
])
<<
56
;
sect
|=
((
u64
)
scsicmd
[
3
])
<<
48
;
block
|=
((
u64
)
scsicmd
[
3
])
<<
48
;
sect
|=
((
u64
)
scsicmd
[
4
])
<<
40
;
block
|=
((
u64
)
scsicmd
[
4
])
<<
40
;
sect
|=
((
u64
)
scsicmd
[
5
])
<<
32
;
block
|=
((
u64
)
scsicmd
[
5
])
<<
32
;
sect
|=
((
u64
)
scsicmd
[
6
])
<<
24
;
block
|=
((
u64
)
scsicmd
[
6
])
<<
24
;
sect
|=
((
u64
)
scsicmd
[
7
])
<<
16
;
block
|=
((
u64
)
scsicmd
[
7
])
<<
16
;
sect
|=
((
u64
)
scsicmd
[
8
])
<<
8
;
block
|=
((
u64
)
scsicmd
[
8
])
<<
8
;
sect
|=
((
u64
)
scsicmd
[
9
]);
block
|=
((
u64
)
scsicmd
[
9
]);
n_
sect
|=
((
u32
)
scsicmd
[
10
])
<<
24
;
n_
block
|=
((
u32
)
scsicmd
[
10
])
<<
24
;
n_
sect
|=
((
u32
)
scsicmd
[
11
])
<<
16
;
n_
block
|=
((
u32
)
scsicmd
[
11
])
<<
16
;
n_
sect
|=
((
u32
)
scsicmd
[
12
])
<<
8
;
n_
block
|=
((
u32
)
scsicmd
[
12
])
<<
8
;
n_
sect
|=
((
u32
)
scsicmd
[
13
]);
n_
block
|=
((
u32
)
scsicmd
[
13
]);
}
}
else
else
return
1
;
return
1
;
if
(
!
n_
sect
)
if
(
!
n_
block
)
return
1
;
return
1
;
if
(
sect
>=
dev_sectors
)
if
(
block
>=
dev_sectors
)
return
1
;
return
1
;
if
((
sect
+
n_sect
)
>
dev_sectors
)
if
((
block
+
n_block
)
>
dev_sectors
)
return
1
;
return
1
;
if
(
lba48
)
{
if
(
lba48
)
{
if
(
n_
sect
>
(
64
*
1024
))
if
(
n_
block
>
(
64
*
1024
))
return
1
;
return
1
;
}
else
{
}
else
{
if
(
n_
sect
>
256
)
if
(
n_
block
>
256
)
return
1
;
return
1
;
}
}
if
(
lba48
)
{
if
(
lba
)
{
tf
->
command
=
ATA_CMD_VERIFY_EXT
;
if
(
lba48
)
{
tf
->
command
=
ATA_CMD_VERIFY_EXT
;
tf
->
hob_nsect
=
(
n_sect
>>
8
)
&
0xff
;
tf
->
hob_nsect
=
(
n_block
>>
8
)
&
0xff
;
tf
->
hob_lbah
=
(
sect
>>
40
)
&
0xff
;
tf
->
hob_lbah
=
(
block
>>
40
)
&
0xff
;
tf
->
hob_lbam
=
(
sect
>>
32
)
&
0xff
;
tf
->
hob_lbam
=
(
block
>>
32
)
&
0xff
;
tf
->
hob_lbal
=
(
sect
>>
24
)
&
0xff
;
tf
->
hob_lbal
=
(
block
>>
24
)
&
0xff
;
}
else
{
}
else
{
tf
->
command
=
ATA_CMD_VERIFY
;
tf
->
command
=
ATA_CMD_VERIFY
;
tf
->
device
|=
(
sect
>>
24
)
&
0xf
;
tf
->
device
|=
(
block
>>
24
)
&
0xf
;
}
}
tf
->
nsect
=
n_block
&
0xff
;
tf
->
nsect
=
n_sect
&
0xff
;
tf
->
lbah
=
(
block
>>
16
)
&
0xff
;
tf
->
lbam
=
(
block
>>
8
)
&
0xff
;
tf
->
lbal
=
block
&
0xff
;
tf
->
lbah
=
(
sect
>>
16
)
&
0xff
;
tf
->
device
|=
ATA_LBA
;
tf
->
lbam
=
(
sect
>>
8
)
&
0xff
;
}
else
{
tf
->
lbal
=
sect
&
0xff
;
/* CHS */
u32
sect
,
head
,
cyl
,
track
;
/* Convert LBA to CHS */
track
=
(
u32
)
block
/
dev
->
sectors
;
cyl
=
track
/
dev
->
heads
;
head
=
track
%
dev
->
heads
;
sect
=
(
u32
)
block
%
dev
->
sectors
+
1
;
DPRINTK
(
"block[%u] track[%u] cyl[%u] head[%u] sect[%u]
\n
"
,
(
u32
)
block
,
track
,
cyl
,
head
,
sect
);
/* Check whether the converted CHS can fit.
Cylinder: 0-65535
Head: 0-15
Sector: 1-255*/
if
((
cyl
>>
16
)
||
(
head
>>
4
)
||
(
sect
>>
8
)
||
(
!
sect
))
return
1
;
tf
->
command
=
ATA_CMD_VERIFY
;
tf
->
nsect
=
n_block
&
0xff
;
/* Sector count 0 means 256 sectors */
tf
->
lbal
=
sect
;
tf
->
lbam
=
cyl
;
tf
->
lbah
=
cyl
>>
8
;
tf
->
device
|=
head
;
}
return
0
;
return
0
;
}
}
...
@@ -533,11 +563,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
...
@@ -533,11 +563,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
static
unsigned
int
ata_scsi_rw_xlat
(
struct
ata_queued_cmd
*
qc
,
u8
*
scsicmd
)
static
unsigned
int
ata_scsi_rw_xlat
(
struct
ata_queued_cmd
*
qc
,
u8
*
scsicmd
)
{
{
struct
ata_taskfile
*
tf
=
&
qc
->
tf
;
struct
ata_taskfile
*
tf
=
&
qc
->
tf
;
struct
ata_device
*
dev
=
qc
->
dev
;
unsigned
int
lba
=
tf
->
flags
&
ATA_TFLAG_LBA
;
unsigned
int
lba48
=
tf
->
flags
&
ATA_TFLAG_LBA48
;
unsigned
int
lba48
=
tf
->
flags
&
ATA_TFLAG_LBA48
;
u64
block
=
0
;
u32
n_block
=
0
;
tf
->
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
tf
->
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
tf
->
protocol
=
qc
->
dev
->
xfer_protocol
;
tf
->
protocol
=
qc
->
dev
->
xfer_protocol
;
tf
->
device
|=
ATA_LBA
;
if
(
scsicmd
[
0
]
==
READ_10
||
scsicmd
[
0
]
==
READ_6
||
if
(
scsicmd
[
0
]
==
READ_10
||
scsicmd
[
0
]
==
READ_6
||
scsicmd
[
0
]
==
READ_16
)
{
scsicmd
[
0
]
==
READ_16
)
{
...
@@ -547,80 +580,111 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
...
@@ -547,80 +580,111 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
tf
->
flags
|=
ATA_TFLAG_WRITE
;
tf
->
flags
|=
ATA_TFLAG_WRITE
;
}
}
/* Calculate the SCSI LBA and transfer length. */
if
(
scsicmd
[
0
]
==
READ_10
||
scsicmd
[
0
]
==
WRITE_10
)
{
if
(
scsicmd
[
0
]
==
READ_10
||
scsicmd
[
0
]
==
WRITE_10
)
{
if
(
lba48
)
{
block
|=
((
u64
)
scsicmd
[
2
])
<<
24
;
tf
->
hob_nsect
=
scsicmd
[
7
];
block
|=
((
u64
)
scsicmd
[
3
])
<<
16
;
tf
->
hob_lbal
=
scsicmd
[
2
];
block
|=
((
u64
)
scsicmd
[
4
])
<<
8
;
block
|=
((
u64
)
scsicmd
[
5
]);
qc
->
nsect
=
((
unsigned
int
)
scsicmd
[
7
]
<<
8
)
|
scsicmd
[
8
];
}
else
{
/* if we don't support LBA48 addressing, the request
* -may- be too large. */
if
((
scsicmd
[
2
]
&
0xf0
)
||
scsicmd
[
7
])
return
1
;
/* stores LBA27:24 in lower 4 bits of device reg */
tf
->
device
|=
scsicmd
[
2
];
qc
->
nsect
=
scsicmd
[
8
];
n_block
|=
((
u32
)
scsicmd
[
7
])
<<
8
;
}
n_block
|=
((
u32
)
scsicmd
[
8
]);
tf
->
nsect
=
scsicmd
[
8
];
tf
->
lbal
=
scsicmd
[
5
];
tf
->
lbam
=
scsicmd
[
4
];
tf
->
lbah
=
scsicmd
[
3
];
VPRINTK
(
"ten-byte command
\n
"
);
VPRINTK
(
"ten-byte command
\n
"
);
return
0
;
}
else
if
(
scsicmd
[
0
]
==
READ_6
||
scsicmd
[
0
]
==
WRITE_6
)
{
}
block
|=
((
u64
)
scsicmd
[
2
])
<<
8
;
block
|=
((
u64
)
scsicmd
[
3
]);
if
(
scsicmd
[
0
]
==
READ_6
||
scsicmd
[
0
]
==
WRITE_6
)
{
n_block
|=
((
u32
)
scsicmd
[
4
]);
qc
->
nsect
=
tf
->
nsect
=
scsicmd
[
4
];
tf
->
lbal
=
scsicmd
[
3
];
tf
->
lbam
=
scsicmd
[
2
];
tf
->
lbah
=
scsicmd
[
1
]
&
0x1f
;
/* mask out reserved bits */
VPRINTK
(
"six-byte command
\n
"
);
VPRINTK
(
"six-byte command
\n
"
);
return
0
;
}
else
if
(
scsicmd
[
0
]
==
READ_16
||
scsicmd
[
0
]
==
WRITE_16
)
{
block
|=
((
u64
)
scsicmd
[
2
])
<<
56
;
block
|=
((
u64
)
scsicmd
[
3
])
<<
48
;
block
|=
((
u64
)
scsicmd
[
4
])
<<
40
;
block
|=
((
u64
)
scsicmd
[
5
])
<<
32
;
block
|=
((
u64
)
scsicmd
[
6
])
<<
24
;
block
|=
((
u64
)
scsicmd
[
7
])
<<
16
;
block
|=
((
u64
)
scsicmd
[
8
])
<<
8
;
block
|=
((
u64
)
scsicmd
[
9
]);
n_block
|=
((
u32
)
scsicmd
[
10
])
<<
24
;
n_block
|=
((
u32
)
scsicmd
[
11
])
<<
16
;
n_block
|=
((
u32
)
scsicmd
[
12
])
<<
8
;
n_block
|=
((
u32
)
scsicmd
[
13
]);
VPRINTK
(
"sixteen-byte command
\n
"
);
}
else
{
DPRINTK
(
"no-byte command
\n
"
);
return
1
;
}
}
if
(
scsicmd
[
0
]
==
READ_16
||
scsicmd
[
0
]
==
WRITE_16
)
{
/* Check and compose ATA command */
/* rule out impossible LBAs and sector counts */
if
(
!
n_block
)
if
(
scsicmd
[
2
]
||
scsicmd
[
3
]
||
scsicmd
[
10
]
||
scsicmd
[
11
])
/* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
return
1
;
return
1
;
if
(
lba
)
{
if
(
lba48
)
{
if
(
lba48
)
{
tf
->
hob_nsect
=
scsicmd
[
12
];
/* The request -may- be too large for LBA48. */
tf
->
hob_lbal
=
scsicmd
[
6
];
if
((
block
>>
48
)
||
(
n_block
>
65536
))
tf
->
hob_lbam
=
scsicmd
[
5
];
tf
->
hob_lbah
=
scsicmd
[
4
];
qc
->
nsect
=
((
unsigned
int
)
scsicmd
[
12
]
<<
8
)
|
scsicmd
[
13
];
}
else
{
/* once again, filter out impossible non-zero values */
if
(
scsicmd
[
4
]
||
scsicmd
[
5
]
||
scsicmd
[
12
]
||
(
scsicmd
[
6
]
&
0xf0
))
return
1
;
return
1
;
/* stores LBA27:24 in lower 4 bits of device reg */
tf
->
hob_nsect
=
(
n_block
>>
8
)
&
0xff
;
tf
->
device
|=
scsicmd
[
6
];
tf
->
hob_lbah
=
(
block
>>
40
)
&
0xff
;
tf
->
hob_lbam
=
(
block
>>
32
)
&
0xff
;
tf
->
hob_lbal
=
(
block
>>
24
)
&
0xff
;
}
else
{
/* LBA28 */
/* The request -may- be too large for LBA28. */
if
((
block
>>
28
)
||
(
n_block
>
256
))
return
1
;
qc
->
nsect
=
scsicmd
[
13
]
;
tf
->
device
|=
(
block
>>
24
)
&
0xf
;
}
}
qc
->
nsect
=
n_block
;
tf
->
nsect
=
n_block
&
0xff
;
tf
->
nsect
=
scsicmd
[
13
];
tf
->
lbah
=
(
block
>>
16
)
&
0xff
;
tf
->
lbal
=
scsicmd
[
9
];
tf
->
lbam
=
(
block
>>
8
)
&
0xff
;
tf
->
lbam
=
scsicmd
[
8
];
tf
->
lbal
=
block
&
0xff
;
tf
->
lbah
=
scsicmd
[
7
];
VPRINTK
(
"sixteen-byte command
\n
"
);
tf
->
device
|=
ATA_LBA
;
return
0
;
}
else
{
/* CHS */
u32
sect
,
head
,
cyl
,
track
;
/* The request -may- be too large for CHS addressing. */
if
((
block
>>
28
)
||
(
n_block
>
256
))
return
1
;
/* Convert LBA to CHS */
track
=
(
u32
)
block
/
dev
->
sectors
;
cyl
=
track
/
dev
->
heads
;
head
=
track
%
dev
->
heads
;
sect
=
(
u32
)
block
%
dev
->
sectors
+
1
;
DPRINTK
(
"block[%u] track[%u] cyl[%u] head[%u] sect[%u]
\n
"
,
(
u32
)
block
,
track
,
cyl
,
head
,
sect
);
/* Check whether the converted CHS can fit.
Cylinder: 0-65535
Head: 0-15
Sector: 1-255*/
if
((
cyl
>>
16
)
||
(
head
>>
4
)
||
(
sect
>>
8
)
||
(
!
sect
))
return
1
;
qc
->
nsect
=
n_block
;
tf
->
nsect
=
n_block
&
0xff
;
/* Sector count 0 means 256 sectors */
tf
->
lbal
=
sect
;
tf
->
lbam
=
cyl
;
tf
->
lbah
=
cyl
>>
8
;
tf
->
device
|=
head
;
}
}
DPRINTK
(
"no-byte command
\n
"
);
return
0
;
return
1
;
}
}
static
int
ata_scsi_qc_complete
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
)
static
int
ata_scsi_qc_complete
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
)
...
@@ -1167,10 +1231,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
...
@@ -1167,10 +1231,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
VPRINTK
(
"ENTER
\n
"
);
VPRINTK
(
"ENTER
\n
"
);
if
(
ata_id_has_lba48
(
args
->
id
))
if
(
ata_id_has_lba
(
args
->
id
))
{
n_sectors
=
ata_id_u64
(
args
->
id
,
100
);
if
(
ata_id_has_lba48
(
args
->
id
))
else
n_sectors
=
ata_id_u64
(
args
->
id
,
100
);
n_sectors
=
ata_id_u32
(
args
->
id
,
60
);
else
n_sectors
=
ata_id_u32
(
args
->
id
,
60
);
}
else
{
/* CHS default translation */
n_sectors
=
args
->
id
[
1
]
*
args
->
id
[
3
]
*
args
->
id
[
6
];
if
(
ata_id_current_chs_valid
(
args
->
id
))
/* CHS current translation */
n_sectors
=
ata_id_u32
(
args
->
id
,
57
);
}
n_sectors
--
;
/* ATA TotalUserSectors - 1 */
n_sectors
--
;
/* ATA TotalUserSectors - 1 */
tmp
=
n_sectors
;
/* note: truncates, if lba48 */
tmp
=
n_sectors
;
/* note: truncates, if lba48 */
...
...
include/linux/ata.h
浏览文件 @
8bf62ece
...
@@ -125,6 +125,7 @@ enum {
...
@@ -125,6 +125,7 @@ enum {
ATA_CMD_PACKET
=
0xA0
,
ATA_CMD_PACKET
=
0xA0
,
ATA_CMD_VERIFY
=
0x40
,
ATA_CMD_VERIFY
=
0x40
,
ATA_CMD_VERIFY_EXT
=
0x42
,
ATA_CMD_VERIFY_EXT
=
0x42
,
ATA_CMD_INIT_DEV_PARAMS
=
0x91
,
/* SETFEATURES stuff */
/* SETFEATURES stuff */
SETFEATURES_XFER
=
0x03
,
SETFEATURES_XFER
=
0x03
,
...
@@ -174,6 +175,7 @@ enum {
...
@@ -174,6 +175,7 @@ enum {
ATA_TFLAG_ISADDR
=
(
1
<<
1
),
/* enable r/w to nsect/lba regs */
ATA_TFLAG_ISADDR
=
(
1
<<
1
),
/* enable r/w to nsect/lba regs */
ATA_TFLAG_DEVICE
=
(
1
<<
2
),
/* enable r/w to device reg */
ATA_TFLAG_DEVICE
=
(
1
<<
2
),
/* enable r/w to device reg */
ATA_TFLAG_WRITE
=
(
1
<<
3
),
/* data dir: host->dev==1 (write) */
ATA_TFLAG_WRITE
=
(
1
<<
3
),
/* data dir: host->dev==1 (write) */
ATA_TFLAG_LBA
=
(
1
<<
4
),
/* enable LBA */
};
};
enum
ata_tf_protocols
{
enum
ata_tf_protocols
{
...
@@ -242,6 +244,18 @@ struct ata_taskfile {
...
@@ -242,6 +244,18 @@ struct ata_taskfile {
((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 0]) )
((u64) (id)[(n) + 0]) )
static
inline
int
ata_id_current_chs_valid
(
u16
*
id
)
{
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
has not been issued to the device then the values of
id[54] to id[56] are vendor specific. */
return
(
id
[
53
]
&
0x01
)
&&
/* Current translation valid */
id
[
54
]
&&
/* cylinders in current translation */
id
[
55
]
&&
/* heads in current translation */
id
[
55
]
<=
16
&&
id
[
56
];
/* sectors in current translation */
}
static
inline
int
atapi_cdb_len
(
u16
*
dev_id
)
static
inline
int
atapi_cdb_len
(
u16
*
dev_id
)
{
{
u16
tmp
=
dev_id
[
0
]
&
0x3
;
u16
tmp
=
dev_id
[
0
]
&
0x3
;
...
...
include/linux/libata.h
浏览文件 @
8bf62ece
...
@@ -95,6 +95,7 @@ enum {
...
@@ -95,6 +95,7 @@ enum {
ATA_DFLAG_LBA48
=
(
1
<<
0
),
/* device supports LBA48 */
ATA_DFLAG_LBA48
=
(
1
<<
0
),
/* device supports LBA48 */
ATA_DFLAG_PIO
=
(
1
<<
1
),
/* device currently in PIO mode */
ATA_DFLAG_PIO
=
(
1
<<
1
),
/* device currently in PIO mode */
ATA_DFLAG_LOCK_SECTORS
=
(
1
<<
2
),
/* don't adjust max_sectors */
ATA_DFLAG_LOCK_SECTORS
=
(
1
<<
2
),
/* don't adjust max_sectors */
ATA_DFLAG_LBA
=
(
1
<<
3
),
/* device supports LBA */
ATA_DEV_UNKNOWN
=
0
,
/* unknown device */
ATA_DEV_UNKNOWN
=
0
,
/* unknown device */
ATA_DEV_ATA
=
1
,
/* ATA device */
ATA_DEV_ATA
=
1
,
/* ATA device */
...
@@ -278,6 +279,11 @@ struct ata_device {
...
@@ -278,6 +279,11 @@ struct ata_device {
u8
xfer_protocol
;
/* taskfile xfer protocol */
u8
xfer_protocol
;
/* taskfile xfer protocol */
u8
read_cmd
;
/* opcode to use on read */
u8
read_cmd
;
/* opcode to use on read */
u8
write_cmd
;
/* opcode to use on write */
u8
write_cmd
;
/* opcode to use on write */
/* for CHS addressing */
u16
cylinders
;
/* Number of cylinders */
u16
heads
;
/* Number of heads */
u16
sectors
;
/* Number of sectors per track */
};
};
struct
ata_port
{
struct
ata_port
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录