Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
R
reform-boundary-uboot
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jack Humbert
reform-boundary-uboot
Commits
4a7cc0f2
Commit
4a7cc0f2
authored
18 years ago
by
Jon Loeliger
Browse files
Options
Downloads
Patches
Plain Diff
Cleanup and lindent new AHCI driver.
parent
dabf9ef8
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
drivers/ahci.c
+138
-142
138 additions, 142 deletions
drivers/ahci.c
with
138 additions
and
142 deletions
drivers/ahci.c
+
138
−
142
View file @
4a7cc0f2
...
@@ -42,7 +42,8 @@
...
@@ -42,7 +42,8 @@
struct
ahci_probe_ent
*
probe_ent
=
NULL
;
struct
ahci_probe_ent
*
probe_ent
=
NULL
;
hd_driveid_t
*
ataid
[
AHCI_MAX_PORTS
];
hd_driveid_t
*
ataid
[
AHCI_MAX_PORTS
];
#define writel_with_flush(a,b) do{writel(a,b);readl(b);}while(0)
#define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0)
static
inline
u32
ahci_port_base
(
u32
base
,
u32
port
)
static
inline
u32
ahci_port_base
(
u32
base
,
u32
port
)
{
{
...
@@ -55,21 +56,25 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
...
@@ -55,21 +56,25 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
{
{
base
=
ahci_port_base
(
base
,
port_idx
);
base
=
ahci_port_base
(
base
,
port_idx
);
port
->
cmd_addr
=
base
;
port
->
cmd_addr
=
base
;
port
->
scr_addr
=
base
+
PORT_SCR
;
port
->
scr_addr
=
base
+
PORT_SCR
;
}
}
#define msleep(a) udelay(a * 1000)
#define msleep(a) udelay(a * 1000)
#define ssleep(a) msleep(a * 1000)
#define ssleep(a) msleep(a * 1000)
static
int
waiting_for_cmd_completed
(
volatile
u8
*
offset
,
int
timeout_msec
,
u32
sign
)
static
int
waiting_for_cmd_completed
(
volatile
u8
*
offset
,
int
timeout_msec
,
u32
sign
)
{
{
int
i
;
int
i
;
u32
status
;
u32
status
;
for
(
i
=
0
;
((
status
=
readl
(
offset
))
&
sign
)
&&
i
<
timeout_msec
;
i
++
)
for
(
i
=
0
;
((
status
=
readl
(
offset
))
&
sign
)
&&
i
<
timeout_msec
;
i
++
)
msleep
(
1
);
msleep
(
1
);
return
(
i
<
timeout_msec
)
?
0
:
-
1
;
return
(
i
<
timeout_msec
)
?
0
:
-
1
;
}
}
...
@@ -80,11 +85,11 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
...
@@ -80,11 +85,11 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
u32
tmp
,
cap_save
;
u32
tmp
,
cap_save
;
u16
tmp16
;
u16
tmp16
;
int
i
,
j
;
int
i
,
j
;
volatile
u8
*
port_mmio
;
volatile
u8
*
port_mmio
;
unsigned
short
vendor
;
unsigned
short
vendor
;
cap_save
=
readl
(
mmio
+
HOST_CAP
);
cap_save
=
readl
(
mmio
+
HOST_CAP
);
cap_save
&=
(
(
1
<<
28
)
|
(
1
<<
17
)
);
cap_save
&=
((
1
<<
28
)
|
(
1
<<
17
));
cap_save
|=
(
1
<<
27
);
cap_save
|=
(
1
<<
27
);
/* global controller reset */
/* global controller reset */
...
@@ -121,13 +126,12 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
...
@@ -121,13 +126,12 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
probe_ent
->
n_ports
=
(
probe_ent
->
cap
&
0x1f
)
+
1
;
probe_ent
->
n_ports
=
(
probe_ent
->
cap
&
0x1f
)
+
1
;
debug
(
"cap 0x%x port_map 0x%x n_ports %d
\n
"
,
debug
(
"cap 0x%x port_map 0x%x n_ports %d
\n
"
,
probe_ent
->
cap
,
probe_ent
->
port_map
,
probe_ent
->
n_ports
);
probe_ent
->
cap
,
probe_ent
->
port_map
,
probe_ent
->
n_ports
);
for
(
i
=
0
;
i
<
probe_ent
->
n_ports
;
i
++
)
{
for
(
i
=
0
;
i
<
probe_ent
->
n_ports
;
i
++
)
{
probe_ent
->
port
[
i
].
port_mmio
=
ahci_port_base
((
u32
)
mmio
,
i
);
probe_ent
->
port
[
i
].
port_mmio
=
ahci_port_base
((
u32
)
mmio
,
i
);
port_mmio
=
(
u8
*
)
probe_ent
->
port
[
i
].
port_mmio
;
port_mmio
=
(
u8
*
)
probe_ent
->
port
[
i
].
port_mmio
;
ahci_setup_port
(
&
probe_ent
->
port
[
i
],
ahci_setup_port
(
&
probe_ent
->
port
[
i
],
(
unsigned
long
)
mmio
,
i
);
(
unsigned
long
)
mmio
,
i
);
/* make sure port is not active */
/* make sure port is not active */
tmp
=
readl
(
port_mmio
+
PORT_CMD
);
tmp
=
readl
(
port_mmio
+
PORT_CMD
);
...
@@ -169,11 +173,11 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
...
@@ -169,11 +173,11 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
/* set irq mask (enables interrupts) */
/* set irq mask (enables interrupts) */
writel
(
DEF_PORT_IRQ
,
port_mmio
+
PORT_IRQ_MASK
);
writel
(
DEF_PORT_IRQ
,
port_mmio
+
PORT_IRQ_MASK
);
/*register linkup ports*/
/*register linkup ports
*/
tmp
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
tmp
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
debug
(
"Port %d status: 0x%x
\n
"
,
i
,
tmp
);
debug
(
"Port %d status: 0x%x
\n
"
,
i
,
tmp
);
if
((
tmp
&
0xf
)
==
0x03
)
if
((
tmp
&
0xf
)
==
0x03
)
probe_ent
->
link_port_map
|=
(
0x01
<<
i
);
probe_ent
->
link_port_map
|=
(
0x01
<<
i
);
}
}
tmp
=
readl
(
mmio
+
HOST_CTL
);
tmp
=
readl
(
mmio
+
HOST_CTL
);
...
@@ -193,7 +197,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
...
@@ -193,7 +197,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
static
void
ahci_print_info
(
struct
ahci_probe_ent
*
probe_ent
)
static
void
ahci_print_info
(
struct
ahci_probe_ent
*
probe_ent
)
{
{
pci_dev_t
pdev
=
probe_ent
->
dev
;
pci_dev_t
pdev
=
probe_ent
->
dev
;
volatile
u8
*
mmio
=
(
volatile
u8
*
)
probe_ent
->
mmio_base
;
volatile
u8
*
mmio
=
(
volatile
u8
*
)
probe_ent
->
mmio_base
;
u32
vers
,
cap
,
impl
,
speed
;
u32
vers
,
cap
,
impl
,
speed
;
const
char
*
speed_s
;
const
char
*
speed_s
;
u16
cc
;
u16
cc
;
...
@@ -221,50 +225,38 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
...
@@ -221,50 +225,38 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
else
else
scc_s
=
"unknown"
;
scc_s
=
"unknown"
;
printf
(
"AHCI %02x%02x.%02x%02x "
printf
(
"AHCI %02x%02x.%02x%02x "
"%u slots %u ports %s Gbps 0x%x impl %s mode
\n
"
"%u slots %u ports %s Gbps 0x%x impl %s mode
\n
"
,
,
(
vers
>>
24
)
&
0xff
,
(
vers
>>
16
)
&
0xff
,
(
vers
>>
24
)
&
0xff
,
(
vers
>>
8
)
&
0xff
,
(
vers
>>
16
)
&
0xff
,
vers
&
0xff
,
(
vers
>>
8
)
&
0xff
,
((
cap
>>
8
)
&
0x1f
)
+
1
,
(
cap
&
0x1f
)
+
1
,
speed_s
,
impl
,
scc_s
);
vers
&
0xff
,
((
cap
>>
8
)
&
0x1f
)
+
1
,
(
cap
&
0x1f
)
+
1
,
speed_s
,
impl
,
scc_s
);
printf
(
"flags: "
printf
(
"flags: "
"%s%s%s%s%s%s"
"%s%s%s%s%s%s"
"%s%s%s%s%s%s%s
\n
"
"%s%s%s%s%s%s%s
\n
"
,
,
cap
&
(
1
<<
31
)
?
"64bit "
:
""
,
cap
&
(
1
<<
30
)
?
"ncq "
:
""
,
cap
&
(
1
<<
31
)
?
"64bit "
:
""
,
cap
&
(
1
<<
28
)
?
"ilck "
:
""
,
cap
&
(
1
<<
30
)
?
"ncq "
:
""
,
cap
&
(
1
<<
27
)
?
"stag "
:
""
,
cap
&
(
1
<<
28
)
?
"ilck "
:
""
,
cap
&
(
1
<<
26
)
?
"pm "
:
""
,
cap
&
(
1
<<
27
)
?
"stag "
:
""
,
cap
&
(
1
<<
25
)
?
"led "
:
""
,
cap
&
(
1
<<
26
)
?
"pm "
:
""
,
cap
&
(
1
<<
24
)
?
"clo "
:
""
,
cap
&
(
1
<<
25
)
?
"led "
:
""
,
cap
&
(
1
<<
19
)
?
"nz "
:
""
,
cap
&
(
1
<<
18
)
?
"only "
:
""
,
cap
&
(
1
<<
24
)
?
"clo "
:
""
,
cap
&
(
1
<<
17
)
?
"pmp "
:
""
,
cap
&
(
1
<<
19
)
?
"nz "
:
""
,
cap
&
(
1
<<
15
)
?
"pio "
:
""
,
cap
&
(
1
<<
18
)
?
"only "
:
""
,
cap
&
(
1
<<
14
)
?
"slum "
:
""
,
cap
&
(
1
<<
17
)
?
"pmp "
:
""
,
cap
&
(
1
<<
13
)
?
"part "
:
""
);
cap
&
(
1
<<
15
)
?
"pio "
:
""
,
cap
&
(
1
<<
14
)
?
"slum "
:
""
,
cap
&
(
1
<<
13
)
?
"part "
:
""
);
}
}
static
int
ahci_init_one
(
pci_dev_t
pdev
)
static
int
ahci_init_one
(
pci_dev_t
pdev
)
{
{
u32
iobase
,
vendor
;
u32
iobase
,
vendor
;
int
rc
;
int
rc
;
memset
((
void
*
)
ataid
,
0
,
sizeof
(
hd_driveid_t
*
)
*
AHCI_MAX_PORTS
);
memset
((
void
*
)
ataid
,
0
,
sizeof
(
hd_driveid_t
*
)
*
AHCI_MAX_PORTS
);
probe_ent
=
malloc
(
sizeof
(
probe_ent
));
probe_ent
=
malloc
(
sizeof
(
probe_ent
));
memset
(
probe_ent
,
0
,
sizeof
(
probe_ent
));
memset
(
probe_ent
,
0
,
sizeof
(
probe_ent
));
...
@@ -273,20 +265,22 @@ static int ahci_init_one (pci_dev_t pdev)
...
@@ -273,20 +265,22 @@ static int ahci_init_one (pci_dev_t pdev)
pci_read_config_dword
(
pdev
,
AHCI_PCI_BAR
,
&
iobase
);
pci_read_config_dword
(
pdev
,
AHCI_PCI_BAR
,
&
iobase
);
iobase
&=
~
0xf
;
iobase
&=
~
0xf
;
probe_ent
->
host_flags
=
ATA_FLAG_SATA
|
ATA_FLAG_NO_LEGACY
probe_ent
->
host_flags
=
ATA_FLAG_SATA
|
ATA_FLAG_MMIO
|
ATA_FLAG_PIO_DMA
|
ATA_FLAG_NO_LEGACY
|
ATA_FLAG_NO_ATAPI
;
|
ATA_FLAG_MMIO
probe_ent
->
pio_mask
=
0x1f
;
|
ATA_FLAG_PIO_DMA
probe_ent
->
udma_mask
=
0x7f
;
/*Fixme,assume to support UDMA6*/
|
ATA_FLAG_NO_ATAPI
;
probe_ent
->
pio_mask
=
0x1f
;
probe_ent
->
udma_mask
=
0x7f
;
/*Fixme,assume to support UDMA6 */
probe_ent
->
mmio_base
=
iobase
;
probe_ent
->
mmio_base
=
iobase
;
/* Take from kernel:
/* Take from kernel:
* JMicron-specific fixup:
* JMicron-specific fixup:
* make sure we're in AHCI mode
* make sure we're in AHCI mode
*/
*/
pci_read_config_word
(
pdev
,
PCI_VENDOR_ID
,
&
vendor
);
pci_read_config_word
(
pdev
,
PCI_VENDOR_ID
,
&
vendor
);
if
(
vendor
==
0x197b
)
if
(
vendor
==
0x197b
)
pci_write_config_byte
(
pdev
,
0x41
,
0xa1
);
pci_write_config_byte
(
pdev
,
0x41
,
0xa1
);
/* initialize adapter */
/* initialize adapter */
...
@@ -298,34 +292,34 @@ static int ahci_init_one (pci_dev_t pdev)
...
@@ -298,34 +292,34 @@ static int ahci_init_one (pci_dev_t pdev)
return
0
;
return
0
;
err_out:
err_out:
return
rc
;
return
rc
;
}
}
#define MAX_DATA_BYTE_COUNT (4*1024*1024)
#define MAX_DATA_BYTE_COUNT (4*1024*1024)
static
int
ahci_fill_sg
(
u8
port
,
unsigned
char
*
buf
,
int
buf_len
)
static
int
ahci_fill_sg
(
u8
port
,
unsigned
char
*
buf
,
int
buf_len
)
{
{
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
struct
ahci_sg
*
ahci_sg
=
pp
->
cmd_tbl_sg
;
struct
ahci_sg
*
ahci_sg
=
pp
->
cmd_tbl_sg
;
u32
sg_count
;
u32
sg_count
;
int
i
;
int
i
;
sg_count
=
((
buf_len
-
1
)
/
MAX_DATA_BYTE_COUNT
)
+
1
;
sg_count
=
((
buf_len
-
1
)
/
MAX_DATA_BYTE_COUNT
)
+
1
;
if
(
sg_count
>
AHCI_MAX_SG
){
if
(
sg_count
>
AHCI_MAX_SG
)
{
printf
(
"Error:Too much sg!
\n
"
);
printf
(
"Error:Too much sg!
\n
"
);
return
-
1
;
return
-
1
;
}
}
for
(
i
=
0
;
i
<
sg_count
;
i
++
)
for
(
i
=
0
;
i
<
sg_count
;
i
++
)
{
{
ahci_sg
->
addr
=
ahci_sg
->
addr
=
cpu_to_le32
((
u32
)
buf
+
i
*
MAX_DATA_BYTE_COUNT
);
cpu_to_le32
((
u32
)
buf
+
i
*
MAX_DATA_BYTE_COUNT
);
ahci_sg
->
addr_hi
=
0
;
ahci_sg
->
addr_hi
=
0
;
ahci_sg
->
flags_size
=
cpu_to_le32
(
0x3fffff
&
ahci_sg
->
flags_size
=
cpu_to_le32
(
0x3fffff
&
(
buf_len
<
MAX_DATA_BYTE_COUNT
(
buf_len
<
MAX_DATA_BYTE_COUNT
?
(
buf_len
-
1
)
?
(
buf_len
-
1
)
:
(
MAX_DATA_BYTE_COUNT
-
1
)));
:
(
MAX_DATA_BYTE_COUNT
-
1
)));
ahci_sg
++
;
ahci_sg
++
;
buf_len
-=
MAX_DATA_BYTE_COUNT
;
buf_len
-=
MAX_DATA_BYTE_COUNT
;
}
}
...
@@ -345,26 +339,25 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
...
@@ -345,26 +339,25 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
static
void
ahci_set_feature
(
u8
port
)
static
void
ahci_set_feature
(
u8
port
)
{
{
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
u32
cmd_fis_len
=
5
;
/* five dwords */
u32
cmd_fis_len
=
5
;
/* five dwords */
u8
fis
[
20
];
u8
fis
[
20
];
/*set feature*/
/*set feature
*/
memset
(
fis
,
0
,
20
);
memset
(
fis
,
0
,
20
);
fis
[
0
]
=
0x27
;
fis
[
0
]
=
0x27
;
fis
[
1
]
=
1
<<
7
;
fis
[
1
]
=
1
<<
7
;
fis
[
2
]
=
ATA_CMD_SETF
;
fis
[
2
]
=
ATA_CMD_SETF
;
fis
[
3
]
=
SETFEATURES_XFER
;
fis
[
3
]
=
SETFEATURES_XFER
;
fis
[
12
]
=
__ilog2
(
probe_ent
->
udma_mask
+
1
)
+
0x40
-
0x01
;
fis
[
12
]
=
__ilog2
(
probe_ent
->
udma_mask
+
1
)
+
0x40
-
0x01
;
memcpy
((
unsigned
char
*
)
pp
->
cmd_tbl
,
fis
,
20
);
memcpy
((
unsigned
char
*
)
pp
->
cmd_tbl
,
fis
,
20
);
ahci_fill_cmd_slot
(
pp
,
cmd_fis_len
);
ahci_fill_cmd_slot
(
pp
,
cmd_fis_len
);
writel
(
1
,
port_mmio
+
PORT_CMD_ISSUE
);
writel
(
1
,
port_mmio
+
PORT_CMD_ISSUE
);
readl
(
port_mmio
+
PORT_CMD_ISSUE
);
readl
(
port_mmio
+
PORT_CMD_ISSUE
);
if
(
waiting_for_cmd_completed
(
port_mmio
+
PORT_CMD_ISSUE
,
150
,
0x1
))
{
if
(
waiting_for_cmd_completed
(
port_mmio
+
PORT_CMD_ISSUE
,
150
,
0x1
))
{
printf
(
"set feature error!
\n
"
);
printf
(
"set feature error!
\n
"
);
}
}
}
}
...
@@ -372,94 +365,94 @@ static void ahci_set_feature(u8 port)
...
@@ -372,94 +365,94 @@ static void ahci_set_feature(u8 port)
static
int
ahci_port_start
(
u8
port
)
static
int
ahci_port_start
(
u8
port
)
{
{
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
u32
port_status
;
u32
port_status
;
u32
mem
;
u32
mem
;
debug
(
"Enter start port: %d
\n
"
,
port
);
debug
(
"Enter start port: %d
\n
"
,
port
);
port_status
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
port_status
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
debug
(
"Port %d status: %x
\n
"
,
port
,
port_status
);
debug
(
"Port %d status: %x
\n
"
,
port
,
port_status
);
if
((
port_status
&
0xf
)
!=
0x03
){
if
((
port_status
&
0xf
)
!=
0x03
)
{
printf
(
"No Link on this port!
\n
"
);
printf
(
"No Link on this port!
\n
"
);
return
-
1
;
return
-
1
;
}
}
mem
=
(
u32
)
malloc
(
AHCI_PORT_PRIV_DMA_SZ
+
2048
);
mem
=
(
u32
)
malloc
(
AHCI_PORT_PRIV_DMA_SZ
+
2048
);
if
(
!
mem
)
{
if
(
!
mem
)
{
free
(
pp
);
free
(
pp
);
printf
(
"No mem for table!
\n
"
);
printf
(
"No mem for table!
\n
"
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
mem
=
(
mem
+
0x800
)
&
(
~
0x7ff
);
/* Aligned to 2048-bytes */
mem
=
(
mem
+
0x800
)
&
(
~
0x7ff
);
/* Aligned to 2048-bytes */
memset
((
u8
*
)
mem
,
0
,
AHCI_PORT_PRIV_DMA_SZ
);
memset
((
u8
*
)
mem
,
0
,
AHCI_PORT_PRIV_DMA_SZ
);
/*
/*
* First item in chunk of DMA memory: 32-slot command table,
* First item in chunk of DMA memory: 32-slot command table,
* 32 bytes each in size
* 32 bytes each in size
*/
*/
pp
->
cmd_slot
=
(
struct
ahci_cmd_hdr
*
)
mem
;
pp
->
cmd_slot
=
(
struct
ahci_cmd_hdr
*
)
mem
;
debug
(
"cmd_slot = 0x%x
\n
"
,
pp
->
cmd_slot
);
debug
(
"cmd_slot = 0x%x
\n
"
,
pp
->
cmd_slot
);
mem
+=
(
AHCI_CMD_SLOT_SZ
+
224
);
mem
+=
(
AHCI_CMD_SLOT_SZ
+
224
);
/*
/*
* Second item: Received-FIS area
* Second item: Received-FIS area
*/
*/
pp
->
rx_fis
=
mem
;
pp
->
rx_fis
=
mem
;
mem
+=
AHCI_RX_FIS_SZ
;
mem
+=
AHCI_RX_FIS_SZ
;
/*
/*
* Third item: data area for storing a single command
* Third item: data area for storing a single command
* and its scatter-gather table
* and its scatter-gather table
*/
*/
pp
->
cmd_tbl
=
mem
;
pp
->
cmd_tbl
=
mem
;
debug
(
"cmd_tbl_dma = 0x%x
\n
"
,
pp
->
cmd_tbl
);
debug
(
"cmd_tbl_dma = 0x%x
\n
"
,
pp
->
cmd_tbl
);
mem
+=
AHCI_CMD_TBL_HDR
;
mem
+=
AHCI_CMD_TBL_HDR
;
pp
->
cmd_tbl_sg
=
(
struct
ahci_sg
*
)
mem
;
pp
->
cmd_tbl_sg
=
(
struct
ahci_sg
*
)
mem
;
writel_with_flush
((
u32
)
pp
->
cmd_slot
,
port_mmio
+
PORT_LST_ADDR
);
writel_with_flush
((
u32
)
pp
->
cmd_slot
,
port_mmio
+
PORT_LST_ADDR
);
writel_with_flush
(
pp
->
rx_fis
,
port_mmio
+
PORT_FIS_ADDR
);
writel_with_flush
(
pp
->
rx_fis
,
port_mmio
+
PORT_FIS_ADDR
);
writel_with_flush
(
PORT_CMD_ICC_ACTIVE
|
PORT_CMD_FIS_RX
|
writel_with_flush
(
PORT_CMD_ICC_ACTIVE
|
PORT_CMD_FIS_RX
|
PORT_CMD_POWER_ON
|
PORT_CMD_SPIN_UP
|
PORT_CMD_POWER_ON
|
PORT_CMD_SPIN_UP
|
PORT_CMD_START
,
port_mmio
+
PORT_CMD
);
PORT_CMD_START
,
port_mmio
+
PORT_CMD
);
debug
(
"Exit start port %d
\n
"
,
port
);
debug
(
"Exit start port %d
\n
"
,
port
);
return
0
;
return
0
;
}
}
static
int
get_ahci_device_data
(
u8
port
,
u8
*
fis
,
int
fis_len
,
u8
*
buf
,
int
buf_len
)
static
int
get_ahci_device_data
(
u8
port
,
u8
*
fis
,
int
fis_len
,
u8
*
buf
,
int
buf_len
)
{
{
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
struct
ahci_ioports
*
pp
=
&
(
probe_ent
->
port
[
port
]);
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
volatile
u8
*
port_mmio
=
(
volatile
u8
*
)
pp
->
port_mmio
;
u32
opts
;
u32
opts
;
u32
port_status
;
u32
port_status
;
int
sg_count
;
int
sg_count
;
debug
(
"Enter get_ahci_device_data: for port %d
\n
"
,
port
);
debug
(
"Enter get_ahci_device_data: for port %d
\n
"
,
port
);
if
(
port
>
probe_ent
->
n_ports
){
if
(
port
>
probe_ent
->
n_ports
)
{
printf
(
"Invaild port number %d
\n
"
,
port
);
printf
(
"Invaild port number %d
\n
"
,
port
);
return
-
1
;
return
-
1
;
}
}
port_status
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
port_status
=
readl
(
port_mmio
+
PORT_SCR_STAT
);
if
((
port_status
&
0xf
)
!=
0x03
){
if
((
port_status
&
0xf
)
!=
0x03
)
{
debug
(
"No Link on port %d!
\n
"
,
port
);
debug
(
"No Link on port %d!
\n
"
,
port
);
return
-
1
;
return
-
1
;
}
}
memcpy
((
unsigned
char
*
)
pp
->
cmd_tbl
,
fis
,
fis_len
);
memcpy
((
unsigned
char
*
)
pp
->
cmd_tbl
,
fis
,
fis_len
);
sg_count
=
ahci_fill_sg
(
port
,
buf
,
buf_len
);
sg_count
=
ahci_fill_sg
(
port
,
buf
,
buf_len
);
opts
=
(
fis_len
>>
2
)
|
(
sg_count
<<
16
)
;
opts
=
(
fis_len
>>
2
)
|
(
sg_count
<<
16
);
ahci_fill_cmd_slot
(
pp
,
opts
);
ahci_fill_cmd_slot
(
pp
,
opts
);
writel_with_flush
(
1
,
port_mmio
+
PORT_CMD_ISSUE
);
writel_with_flush
(
1
,
port_mmio
+
PORT_CMD_ISSUE
);
...
@@ -469,7 +462,7 @@ static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf, int buf_
...
@@ -469,7 +462,7 @@ static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf, int buf_
return
-
1
;
return
-
1
;
}
}
debug
(
"get_ahci_device_data: %d byte transferred.
\n
"
,
debug
(
"get_ahci_device_data: %d byte transferred.
\n
"
,
pp
->
cmd_slot
->
status
);
pp
->
cmd_slot
->
status
);
return
0
;
return
0
;
}
}
...
@@ -478,7 +471,7 @@ static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf, int buf_
...
@@ -478,7 +471,7 @@ static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf, int buf_
static
char
*
ata_id_strcpy
(
u16
*
target
,
u16
*
src
,
int
len
)
static
char
*
ata_id_strcpy
(
u16
*
target
,
u16
*
src
,
int
len
)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
len
/
2
;
i
++
)
for
(
i
=
0
;
i
<
len
/
2
;
i
++
)
target
[
i
]
=
le16_to_cpu
(
src
[
i
]);
target
[
i
]
=
le16_to_cpu
(
src
[
i
]);
return
(
char
*
)
target
;
return
(
char
*
)
target
;
}
}
...
@@ -503,6 +496,7 @@ static void dump_ataid(hd_driveid_t *ataid)
...
@@ -503,6 +496,7 @@ static void dump_ataid(hd_driveid_t *ataid)
debug
(
"(93)ataid->hw_config = 0x%x
\n
"
,
ataid
->
hw_config
);
debug
(
"(93)ataid->hw_config = 0x%x
\n
"
,
ataid
->
hw_config
);
}
}
/*
/*
* SCSI INQUIRY command operation.
* SCSI INQUIRY command operation.
*/
*/
...
@@ -511,7 +505,7 @@ static int ata_scsiop_inquiry(ccb *pccb)
...
@@ -511,7 +505,7 @@ static int ata_scsiop_inquiry(ccb *pccb)
u8
hdr
[]
=
{
u8
hdr
[]
=
{
0
,
0
,
0
,
0
,
0x5
,
/* claim SPC-3 version compatibility */
0x5
,
/* claim SPC-3 version compatibility */
2
,
2
,
95
-
4
,
95
-
4
,
};
};
...
@@ -524,33 +518,33 @@ static int ata_scsiop_inquiry(ccb *pccb)
...
@@ -524,33 +518,33 @@ static int ata_scsiop_inquiry(ccb *pccb)
memcpy
(
pccb
->
pdata
,
hdr
,
sizeof
(
hdr
));
memcpy
(
pccb
->
pdata
,
hdr
,
sizeof
(
hdr
));
if
(
pccb
->
datalen
<=
35
)
if
(
pccb
->
datalen
<=
35
)
return
0
;
return
0
;
memset
(
fis
,
0
,
20
);
memset
(
fis
,
0
,
20
);
/* Construct the FIS */
/* Construct the FIS */
fis
[
0
]
=
0x27
;
/* Host to device FIS. */
fis
[
0
]
=
0x27
;
/* Host to device FIS. */
fis
[
1
]
=
1
<<
7
;
/* Command FIS. */
fis
[
1
]
=
1
<<
7
;
/* Command FIS. */
fis
[
2
]
=
ATA_CMD_IDENT
;
/* Command byte. */
fis
[
2
]
=
ATA_CMD_IDENT
;
/* Command byte. */
/* Read id from sata */
/* Read id from sata */
port
=
pccb
->
target
;
port
=
pccb
->
target
;
if
(
!
(
tmpid
=
malloc
(
sizeof
(
hd_driveid_t
))))
if
(
!
(
tmpid
=
malloc
(
sizeof
(
hd_driveid_t
))))
return
-
ENOMEM
;
return
-
ENOMEM
;
if
(
get_ahci_device_data
(
port
,
(
u8
*
)
&
fis
,
20
,
if
(
get_ahci_device_data
(
port
,
(
u8
*
)
&
fis
,
20
,
tmpid
,
sizeof
(
hd_driveid_t
))){
tmpid
,
sizeof
(
hd_driveid_t
)))
{
debug
(
"scsi_ahci: SCSI inquiry command failure.
\n
"
);
debug
(
"scsi_ahci: SCSI inquiry command failure.
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
if
(
ataid
[
port
])
if
(
ataid
[
port
])
free
(
ataid
[
port
]);
free
(
ataid
[
port
]);
ataid
[
port
]
=
(
hd_driveid_t
*
)
tmpid
;
ataid
[
port
]
=
(
hd_driveid_t
*
)
tmpid
;
memcpy
(
&
pccb
->
pdata
[
8
],
"ATA "
,
8
);
memcpy
(
&
pccb
->
pdata
[
8
],
"ATA "
,
8
);
ata_id_strcpy
((
u16
*
)
&
pccb
->
pdata
[
16
],
(
u16
*
)
ataid
[
port
]
->
model
,
16
);
ata_id_strcpy
((
u16
*
)
&
pccb
->
pdata
[
16
],
(
u16
*
)
ataid
[
port
]
->
model
,
16
);
ata_id_strcpy
((
u16
*
)
&
pccb
->
pdata
[
32
],
(
u16
*
)
ataid
[
port
]
->
fw_rev
,
4
);
ata_id_strcpy
((
u16
*
)
&
pccb
->
pdata
[
32
],
(
u16
*
)
ataid
[
port
]
->
fw_rev
,
4
);
dump_ataid
(
ataid
[
port
]);
dump_ataid
(
ataid
[
port
]);
return
0
;
return
0
;
...
@@ -560,15 +554,15 @@ static int ata_scsiop_inquiry(ccb *pccb)
...
@@ -560,15 +554,15 @@ static int ata_scsiop_inquiry(ccb *pccb)
/*
/*
* SCSI READ10 command operation.
* SCSI READ10 command operation.
*/
*/
static
int
ata_scsiop_read10
(
ccb
*
pccb
)
static
int
ata_scsiop_read10
(
ccb
*
pccb
)
{
{
u64
lba
=
0
;
u64
lba
=
0
;
u32
len
=
0
;
u32
len
=
0
;
u8
fis
[
20
];
u8
fis
[
20
];
lba
=
(((
u64
)
pccb
->
cmd
[
2
])
<<
24
)
|
(((
u64
)
pccb
->
cmd
[
3
])
<<
16
)
lba
=
(((
u64
)
pccb
->
cmd
[
2
])
<<
24
)
|
(((
u64
)
pccb
->
cmd
[
3
])
<<
16
)
|
(((
u64
)
pccb
->
cmd
[
4
])
<<
8
)
|
((
u64
)
pccb
->
cmd
[
5
]);
|
(((
u64
)
pccb
->
cmd
[
4
])
<<
8
)
|
((
u64
)
pccb
->
cmd
[
5
]);
len
=
(((
u32
)
pccb
->
cmd
[
7
])
<<
8
)
|
((
u32
)
pccb
->
cmd
[
8
]);
len
=
(((
u32
)
pccb
->
cmd
[
7
])
<<
8
)
|
((
u32
)
pccb
->
cmd
[
8
]);
/* For 10-byte and 16-byte SCSI R/W commands, transfer
/* For 10-byte and 16-byte SCSI R/W commands, transfer
* length 0 means transfer 0 block of data.
* length 0 means transfer 0 block of data.
...
@@ -577,15 +571,16 @@ static int ata_scsiop_read10(ccb *pccb)
...
@@ -577,15 +571,16 @@ static int ata_scsiop_read10(ccb *pccb)
*
*
* WARNING: one or two older ATA drives treat 0 as 0...
* WARNING: one or two older ATA drives treat 0 as 0...
*/
*/
if
(
!
len
)
return
0
;
if
(
!
len
)
return
0
;
memset
(
fis
,
0
,
20
);
memset
(
fis
,
0
,
20
);
/* Construct the FIS */
/* Construct the FIS */
fis
[
0
]
=
0x27
;
/* Host to device FIS. */
fis
[
0
]
=
0x27
;
/* Host to device FIS. */
fis
[
1
]
=
1
<<
7
;
/* Command FIS. */
fis
[
1
]
=
1
<<
7
;
/* Command FIS. */
fis
[
2
]
=
ATA_CMD_RD_DMA
;
/* Command byte. */
fis
[
2
]
=
ATA_CMD_RD_DMA
;
/* Command byte. */
/* LBA address, only support LBA28 in this driver*/
/* LBA address, only support LBA28 in this driver
*/
fis
[
4
]
=
pccb
->
cmd
[
5
];
fis
[
4
]
=
pccb
->
cmd
[
5
];
fis
[
5
]
=
pccb
->
cmd
[
4
];
fis
[
5
]
=
pccb
->
cmd
[
4
];
fis
[
6
]
=
pccb
->
cmd
[
3
];
fis
[
6
]
=
pccb
->
cmd
[
3
];
...
@@ -596,8 +591,8 @@ static int ata_scsiop_read10(ccb *pccb)
...
@@ -596,8 +591,8 @@ static int ata_scsiop_read10(ccb *pccb)
fis
[
13
]
=
pccb
->
cmd
[
7
];
fis
[
13
]
=
pccb
->
cmd
[
7
];
/* Read from ahci */
/* Read from ahci */
if
(
get_ahci_device_data
(
pccb
->
target
,
(
u8
*
)
&
fis
,
20
,
if
(
get_ahci_device_data
(
pccb
->
target
,
(
u8
*
)
&
fis
,
20
,
pccb
->
pdata
,
pccb
->
datalen
)){
pccb
->
pdata
,
pccb
->
datalen
))
{
debug
(
"scsi_ahci: SCSI READ10 command failure.
\n
"
);
debug
(
"scsi_ahci: SCSI READ10 command failure.
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -613,16 +608,16 @@ static int ata_scsiop_read_capacity10(ccb *pccb)
...
@@ -613,16 +608,16 @@ static int ata_scsiop_read_capacity10(ccb *pccb)
{
{
u8
buf
[
8
];
u8
buf
[
8
];
if
(
!
ataid
[
pccb
->
target
])
{
if
(
!
ataid
[
pccb
->
target
])
{
printf
(
"scsi_ahci: SCSI READ CAPACITY10 command failure. "
printf
(
"scsi_ahci: SCSI READ CAPACITY10 command failure. "
"
\t
No ATA info!
\n
"
"
\t
No ATA info!
\n
"
"
\t
Please run SCSI commmand INQUIRY firstly!
\n
"
);
"
\t
Please run SCSI commmand INQUIRY firstly!
\n
"
);
return
-
EPERM
;
return
-
EPERM
;
}
}
memset
(
buf
,
0
,
8
);
memset
(
buf
,
0
,
8
);
*
(
u32
*
)
buf
=
le32_to_cpu
(
ataid
[
pccb
->
target
]
->
lba_capacity
);
*
(
u32
*
)
buf
=
le32_to_cpu
(
ataid
[
pccb
->
target
]
->
lba_capacity
);
buf
[
6
]
=
512
>>
8
;
buf
[
6
]
=
512
>>
8
;
buf
[
7
]
=
512
&
0xff
;
buf
[
7
]
=
512
&
0xff
;
...
@@ -641,11 +636,12 @@ static int ata_scsiop_test_unit_ready(ccb *pccb)
...
@@ -641,11 +636,12 @@ static int ata_scsiop_test_unit_ready(ccb *pccb)
return
(
ataid
[
pccb
->
target
])
?
0
:
-
EPERM
;
return
(
ataid
[
pccb
->
target
])
?
0
:
-
EPERM
;
}
}
int
scsi_exec
(
ccb
*
pccb
)
int
scsi_exec
(
ccb
*
pccb
)
{
{
int
ret
;
int
ret
;
switch
(
pccb
->
cmd
[
0
])
{
switch
(
pccb
->
cmd
[
0
])
{
case
SCSI_READ10
:
case
SCSI_READ10
:
ret
=
ata_scsiop_read10
(
pccb
);
ret
=
ata_scsiop_read10
(
pccb
);
break
;
break
;
...
@@ -663,8 +659,8 @@ int scsi_exec(ccb *pccb)
...
@@ -663,8 +659,8 @@ int scsi_exec(ccb *pccb)
return
FALSE
;
return
FALSE
;
}
}
if
(
ret
)
{
if
(
ret
)
{
debug
(
"SCSI command 0x%02x ret errno %d
\n
"
,
pccb
->
cmd
[
0
],
ret
);
debug
(
"SCSI command 0x%02x ret errno %d
\n
"
,
pccb
->
cmd
[
0
],
ret
);
return
FALSE
;
return
FALSE
;
}
}
return
TRUE
;
return
TRUE
;
...
@@ -681,13 +677,13 @@ void scsi_low_level_init(int busdevfunc)
...
@@ -681,13 +677,13 @@ void scsi_low_level_init(int busdevfunc)
linkmap
=
probe_ent
->
link_port_map
;
linkmap
=
probe_ent
->
link_port_map
;
for
(
i
=
0
;
i
<
CFG_SCSI_MAX_SCSI_ID
;
i
++
){
for
(
i
=
0
;
i
<
CFG_SCSI_MAX_SCSI_ID
;
i
++
)
{
if
(
((
linkmap
>>
i
)
&
0x01
)
){
if
(
((
linkmap
>>
i
)
&
0x01
))
{
if
(
ahci_port_start
((
u8
)
i
)){
if
(
ahci_port_start
((
u8
)
i
))
{
printf
(
"Can not start port %d
\n
"
,
i
);
printf
(
"Can not start port %d
\n
"
,
i
);
continue
;
continue
;
}
}
ahci_set_feature
((
u8
)
i
);
ahci_set_feature
((
u8
)
i
);
}
}
}
}
}
}
...
@@ -695,12 +691,12 @@ void scsi_low_level_init(int busdevfunc)
...
@@ -695,12 +691,12 @@ void scsi_low_level_init(int busdevfunc)
void
scsi_bus_reset
(
void
)
void
scsi_bus_reset
(
void
)
{
{
/*Not implement*/
/*Not implement*/
}
}
void
scsi_print_error
(
ccb
*
pccb
)
void
scsi_print_error
(
ccb
*
pccb
)
{
{
/*The ahci error info can be read in the ahci driver*/
/*The ahci error info can be read in the ahci driver*/
}
}
#endif
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment