Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
6a573df8
Commit
6a573df8
authored
Aug 02, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Write multiple sectors from a buffer pointed by S/G list
parent
bbfc3d59
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
52 additions
and
73 deletions
+52
-73
ahci_elphel.c
src/drivers/ata/ahci_elphel.c
+52
-73
No files found.
src/drivers/ata/ahci_elphel.c
View file @
6a573df8
...
@@ -442,12 +442,6 @@ static ssize_t elphel_test_write(struct device *dev, struct device_attribute *at
...
@@ -442,12 +442,6 @@ static ssize_t elphel_test_write(struct device *dev, struct device_attribute *at
msleep
(
1
);
msleep
(
1
);
}
}
// printk(KERN_DEBUG ">>> dump test buffer after reading: %d bytes\n", TEST_BUFF_SZ);
// dma_sync_single_for_cpu(dev, pElphel_buf->d2h_paddr, pElphel_buf->d2h_size, DMA_FROM_DEVICE);
// print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, test_buff, TEST_BUFF_SZ);
// dma_sync_single_for_device(dev, pElphel_buf->d2h_paddr, pElphel_buf->d2h_size, DMA_FROM_DEVICE);
// printk(KERN_DEBUG ">>> buffer has been mapped for device\n");
printk
(
KERN_DEBUG
">>> dump test buffer after reading: %d bytes
\n
"
,
TEST_BUFF_SZ
);
printk
(
KERN_DEBUG
">>> dump test buffer after reading: %d bytes
\n
"
,
TEST_BUFF_SZ
);
dma_unmap_sg
(
dev
,
sgl
,
sg_elems
,
DMA_FROM_DEVICE
);
dma_unmap_sg
(
dev
,
sgl
,
sg_elems
,
DMA_FROM_DEVICE
);
for
(
i
=
0
;
i
<
sg_elems
;
i
++
)
{
for
(
i
=
0
;
i
<
sg_elems
;
i
++
)
{
...
@@ -456,42 +450,36 @@ static ssize_t elphel_test_write(struct device *dev, struct device_attribute *at
...
@@ -456,42 +450,36 @@ static ssize_t elphel_test_write(struct device *dev, struct device_attribute *at
sg_copy_to_buffer
(
&
sgl
[
i
],
1
,
buff
,
TEST_BUFF_SZ
);
sg_copy_to_buffer
(
&
sgl
[
i
],
1
,
buff
,
TEST_BUFF_SZ
);
print_hex_dump_bytes
(
""
,
DUMP_PREFIX_OFFSET
,
buff
,
TEST_BUFF_SZ
);
print_hex_dump_bytes
(
""
,
DUMP_PREFIX_OFFSET
,
buff
,
TEST_BUFF_SZ
);
}
}
/* end of read test */
/* end of read test */
// printk(KERN_DEBUG ">>> interrupt flag has been cleared\n");
printk
(
KERN_DEBUG
">>> *** proceeding to write test *** <<<
\n
"
);
// printk(KERN_DEBUG ">>> dump of SG list area\n");
// dma_sync_single_for_cpu(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
/* write test */
// print_hex_dump_bytes("", DUMP_PREFIX_NONE, test_buff, TEST_BUFF_SZ);
for_each_sg
(
sgl
,
sg_ptr
,
SG_TBL_SZ
,
n_elem
)
{
// dma_sync_single_for_device(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
u8
pattern_buff
[
TEST_BUFF_SZ
];
// /* end of read test */
memset
(
pattern_buff
,
0x5a
,
TEST_BUFF_SZ
);
//
sg_copy_from_buffer
(
sg_ptr
,
1
,
pattern_buff
,
TEST_BUFF_SZ
);
// /* write test */
}
// printk(KERN_DEBUG ">>> filling test buffer: %d bytes\n", TEST_BUFF_SZ);
dma_map_sg
(
dev
,
sgl
,
sg_elems
,
DMA_TO_DEVICE
);
// dma_sync_single_for_cpu(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
// for (i = 0; i < TEST_BUFF_SZ - 1; i += 2) {
printk
(
KERN_DEBUG
">>> trying to write data from sg list
\n
"
);
// test_buff[i] = 0xaa;
elphel_write_dma
(
port
,
lba_addr
,
sg_elems
,
sgl
,
sg_elems
);
// test_buff[i + 1] = 0x55;
printk
(
KERN_DEBUG
">>> command has been issued
\n
"
);
// }
// print_hex_dump_bytes("", DUMP_PREFIX_NONE, test_buff, TEST_BUFF_SZ);
while
(
dpriv
->
flags
&
IRQ_SIMPLE
)
{
// dma_sync_single_for_device(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
printk_once
(
KERN_DEBUG
">>> waiting for interrupt
\n
"
);
// printk(KERN_DEBUG ">>> buffer has been mapped\n");
msleep
(
1
);
//
}
// sg_init_one(&sg, pElphel_buf->h2d_vaddr, TEST_BUFF_SZ);
//
printk
(
KERN_DEBUG
">>> dump test buffer after writing: %d bytes
\n
"
,
TEST_BUFF_SZ
);
// printk(KERN_DEBUG ">>> trying to read data to sg list\n");
dma_unmap_sg
(
dev
,
sgl
,
sg_elems
,
DMA_TO_DEVICE
);
// elphel_read_dma(port, SDA2_LBA_ADDR, 1, &sg, 1);
for
(
i
=
0
;
i
<
sg_elems
;
i
++
)
{
// printk(KERN_DEBUG ">>> command has been issued\n");
dev_dbg
(
dev
,
">>> sector %i
\n
"
,
i
);
// /* end of write test */
u8
buff
[
TEST_BUFF_SZ
];
//
sg_copy_to_buffer
(
&
sgl
[
i
],
1
,
buff
,
TEST_BUFF_SZ
);
//// while (dpriv->flags & IRQ_SIMPLE) {
print_hex_dump_bytes
(
""
,
DUMP_PREFIX_OFFSET
,
buff
,
TEST_BUFF_SZ
);
//// msleep(1);
}
//// }
/* end of write test */
// printk(KERN_DEBUG ">>> interrupt flag has been cleared\n");
// printk(KERN_DEBUG ">>> dump of SG list area\n");
// dma_sync_single_for_cpu(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
// print_hex_dump_bytes("", DUMP_PREFIX_NONE, test_buff, TEST_BUFF_SZ);
// dma_sync_single_for_device(dev, pElphel_buf->h2d_paddr, pElphel_buf->h2d_size, DMA_TO_DEVICE);
return
buff_sz
;
return
buff_sz
;
}
}
...
@@ -511,10 +499,19 @@ inline void prep_cfis(u8 *cmd_tbl, ///< pointer to the beginning o
...
@@ -511,10 +499,19 @@ inline void prep_cfis(u8 *cmd_tbl, ///< pointer to the beginning o
* a command in ATA/ATAPI command set documentation
* a command in ATA/ATAPI command set documentation
*/
*/
switch
(
cmd
)
{
switch
(
cmd
)
{
case
ATA_CMD_WRITE
:
device
=
0xe0
|
((
start_addr
>>
24
)
&
0x0f
);
ctrl
=
0x08
;
/* this is 28-bit command; 4 bits of the address have already been
* placed to Device register, invalidate the remaining (if any) upper
* bits of the address and leave only 24 significant bits (just in case)
*/
start_addr
&=
0xffffff
;
break
;
case
ATA_CMD_WRITE_EXT
:
case
ATA_CMD_WRITE_EXT
:
// not verified yet
// not verified yet
device
=
0x00
;
device
=
0x00
;
ctrl
=
0x0
0
;
ctrl
=
0x0
8
;
break
;
break
;
case
ATA_CMD_READ
:
case
ATA_CMD_READ
:
device
=
0xe0
|
((
start_addr
>>
24
)
&
0x0f
);
device
=
0xe0
|
((
start_addr
>>
24
)
&
0x0f
);
...
@@ -572,18 +569,15 @@ inline void prep_prdt(struct scatterlist *sgl, ///< pointer to S/G list which
...
@@ -572,18 +569,15 @@ inline void prep_prdt(struct scatterlist *sgl, ///< pointer to S/G list which
}
}
}
}
static
int
elphel_write_dma
(
struct
ata_port
*
ap
,
u64
start
,
u16
count
,
struct
scatterlist
*
sg
,
unsigned
int
elem
)
static
int
elphel_write_dma
(
struct
ata_port
*
ap
,
u64
start
,
u16
count
,
struct
scatterlist
*
sg
l
,
unsigned
int
elem
)
{
{
u32
opts
;
u32
opts
;
const
u32
cmd_fis_len
=
5
;
unsigned
int
n_elem
;
// void *cmd_tbl;
u8
*
cmd_tbl
;
u8
*
cmd_tbl
;
u8
cmd
;
unsigned
int
slot_num
=
0
;
unsigned
int
slot_num
=
0
;
struct
ahci_port_priv
*
pp
=
ap
->
private_data
;
struct
ahci_port_priv
*
pp
=
ap
->
private_data
;
struct
ahci_host_priv
*
hpriv
=
ap
->
host
->
private_data
;
struct
ahci_host_priv
*
hpriv
=
ap
->
host
->
private_data
;
struct
elphel_ahci_priv
*
dpriv
=
hpriv
->
plat_data
;
struct
elphel_ahci_priv
*
dpriv
=
hpriv
->
plat_data
;
struct
scatterlist
*
sg_ptr
;
struct
ahci_sg
*
ahci_sg
;
struct
ahci_sg
*
ahci_sg
;
void
__iomem
*
port_mmio
=
ahci_port_base
(
ap
);
void
__iomem
*
port_mmio
=
ahci_port_base
(
ap
);
...
@@ -592,42 +586,27 @@ static int elphel_write_dma(struct ata_port *ap, u64 start, u16 count, struct sc
...
@@ -592,42 +586,27 @@ static int elphel_write_dma(struct ata_port *ap, u64 start, u16 count, struct sc
/* prepare command FIS */
/* prepare command FIS */
dma_sync_single_for_cpu
(
ap
->
dev
,
pp
->
cmd_tbl_dma
,
AHCI_CMD_TBL_AR_SZ
,
DMA_TO_DEVICE
);
dma_sync_single_for_cpu
(
ap
->
dev
,
pp
->
cmd_tbl_dma
,
AHCI_CMD_TBL_AR_SZ
,
DMA_TO_DEVICE
);
cmd_tbl
=
pp
->
cmd_tbl
+
slot_num
*
AHCI_CMD_TBL_SZ
;
cmd_tbl
=
pp
->
cmd_tbl
+
slot_num
*
AHCI_CMD_TBL_SZ
;
cmd_tbl
[
0
]
=
0x27
;
// H2D register FIS
if
(
start
&
~
ADDR_MASK_28_BIT
)
cmd_tbl
[
1
]
=
0x80
;
// set C = 1
cmd
=
ATA_CMD_WRITE_EXT
;
cmd_tbl
[
2
]
=
ATA_CMD_WRITE
;
// ATA WRITE DMA command as described in ATA/ATAPI command set
else
cmd_tbl
[
3
]
=
0
;
// features(7:0)
cmd
=
ATA_CMD_WRITE
;
cmd_tbl
[
4
]
=
(
start
>>
0
)
&
0xff
;
// LBA(7:0)
prep_cfis
(
cmd_tbl
,
cmd
,
start
,
count
);
cmd_tbl
[
5
]
=
(
start
>>
8
)
&
0xff
;
// LBA(15:8)
cmd_tbl
[
6
]
=
(
start
>>
16
)
&
0xff
;
// LBA(23:16)
cmd_tbl
[
7
]
=
0
;
// device
cmd_tbl
[
8
]
=
(
start
>>
24
)
&
0xff
;
// LBA(31:24)
cmd_tbl
[
9
]
=
(
start
>>
32
)
&
0xff
;
// LBA(39:32)
cmd_tbl
[
10
]
=
(
start
>>
40
)
&
0xff
;
// LBA(47:40)
cmd_tbl
[
11
]
=
0
;
// features(15:8)
cmd_tbl
[
12
]
=
(
count
>>
0
)
&
0xff
;
// count(7:0)
cmd_tbl
[
13
]
=
(
count
>>
8
)
&
0xff
;
// count(15:8)
cmd_tbl
[
14
]
=
0
;
// ICC (isochronous command completion)
cmd_tbl
[
15
]
=
0
;
// control
/* prepare physical region descriptor table */
/* prepare physical region descriptor table */
n_elem
=
0
;
ahci_sg
=
pp
->
cmd_tbl
+
slot_num
*
AHCI_CMD_TBL_SZ
+
AHCI_CMD_TBL_HDR_SZ
;
ahci_sg
=
pp
->
cmd_tbl
+
slot_num
*
AHCI_CMD_TBL_SZ
+
AHCI_CMD_TBL_HDR_SZ
;
prep_prdt
(
sg
,
elem
,
ahci_sg
);
prep_prdt
(
sgl
,
elem
,
ahci_sg
);
// for_each_sg(sg, sg_ptr, elem, n_elem) {
// dma_addr_t addr = sg_dma_address(sg_ptr);
// u32 sg_len = sg_dma_len(sg_ptr);
//
// ahci_sg[n_elem].addr = cpu_to_le32(addr & 0xffffffff);
// ahci_sg[n_elem].addr_hi = cpu_to_le32((addr >> 16) >> 16);
// ahci_sg[n_elem].flags_size = cpu_to_le32(sg_len - 1);
// }
/* prepare command header */
/* prepare command header */
opts
=
cmd_fis_len
|
(
n_elem
<<
16
)
|
AHCI_CMD_WRITE
|
AHCI_CMD_PREFETCH
|
AHCI_CMD_CLR_BUSY
;
opts
=
CMD_FIS_LEN
|
(
elem
<<
16
)
|
AHCI_CMD_PREFETCH
|
AHCI_CMD_CLR_BUSY
|
AHCI_CMD_WRITE
;
ahci_fill_cmd_slot
(
pp
,
slot_num
,
opts
);
ahci_fill_cmd_slot
(
pp
,
slot_num
,
opts
);
printk
(
KERN_DEBUG
">>> dump command table content, first %d bytes, phys addr = 0x%x:
\n
"
,
TEST_BUFF_SZ
,
pp
->
cmd_tbl_dma
);
print_hex_dump_bytes
(
""
,
DUMP_PREFIX_OFFSET
,
pp
->
cmd_tbl
,
TEST_BUFF_SZ
);
dma_sync_single_for_device
(
ap
->
dev
,
pp
->
cmd_tbl_dma
,
AHCI_CMD_TBL_AR_SZ
,
DMA_TO_DEVICE
);
dma_sync_single_for_device
(
ap
->
dev
,
pp
->
cmd_tbl_dma
,
AHCI_CMD_TBL_AR_SZ
,
DMA_TO_DEVICE
);
/* issue command */
/* issue command */
writel
(
0x11
,
port_mmio
+
PORT_CMD
);
writel
(
1
<<
slot_num
,
port_mmio
+
PORT_CMD_ISSUE
);
writel
(
1
<<
slot_num
,
port_mmio
+
PORT_CMD_ISSUE
);
return
0
;
return
0
;
...
...
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