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
23700c6b
Commit
23700c6b
authored
Oct 22, 2003
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[libata] fill in a lot more Promise PDC20621 support
parent
402ba7d3
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
346 additions
and
80 deletions
+346
-80
drivers/scsi/sata_promise.c
drivers/scsi/sata_promise.c
+346
-80
No files found.
drivers/scsi/sata_promise.c
View file @
23700c6b
...
@@ -41,6 +41,7 @@ enum {
...
@@ -41,6 +41,7 @@ enum {
PDC_PRD_TBL
=
0x44
,
/* Direct command DMA table addr */
PDC_PRD_TBL
=
0x44
,
/* Direct command DMA table addr */
PDC_PKT_SUBMIT
=
0x40
,
/* Command packet pointer addr */
PDC_PKT_SUBMIT
=
0x40
,
/* Command packet pointer addr */
PDC_HDMA_PKT_SUBMIT
=
0x100
,
/* Host DMA packet pointer addr */
PDC_INT_SEQMASK
=
0x40
,
/* Mask of asserted SEQ INTs */
PDC_INT_SEQMASK
=
0x40
,
/* Mask of asserted SEQ INTs */
PDC_TBG_MODE
=
0x41
,
/* TBG mode */
PDC_TBG_MODE
=
0x41
,
/* TBG mode */
PDC_FLASH_CTL
=
0x44
,
/* Flash control register */
PDC_FLASH_CTL
=
0x44
,
/* Flash control register */
...
@@ -50,6 +51,12 @@ enum {
...
@@ -50,6 +51,12 @@ enum {
PDC_20621_SEQCTL
=
0x400
,
PDC_20621_SEQCTL
=
0x400
,
PDC_20621_SEQMASK
=
0x480
,
PDC_20621_SEQMASK
=
0x480
,
/* chosen, not constant, values; we design our own DIMM mem map */
PDC_20621_DIMM_WINDOW
=
0x0C
,
/* page# for 32K DIMM window */
PDC_20621_DIMM_BASE
=
0x00200000
,
PDC_20621_HOST_PRD
=
64
,
PDC_20621_ATA_PRD
=
72
,
PDC_CHIP0_OFS
=
0xC0000
,
/* offset of chip #0 */
PDC_CHIP0_OFS
=
0xC0000
,
/* offset of chip #0 */
board_2037x
=
0
,
/* FastTrak S150 TX2plus */
board_2037x
=
0
,
/* FastTrak S150 TX2plus */
...
@@ -61,6 +68,8 @@ enum {
...
@@ -61,6 +68,8 @@ enum {
struct
pdc_port_priv
{
struct
pdc_port_priv
{
u8
prd_buf
[
ATA_PRD_SZ
*
ATA_MAX_PRD
];
u8
pkt_buf
[
256
];
u8
*
pkt
;
u8
*
pkt
;
dma_addr_t
pkt_dma
;
dma_addr_t
pkt_dma
;
};
};
...
@@ -74,14 +83,20 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev,
...
@@ -74,14 +83,20 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev,
unsigned
int
udma
);
unsigned
int
udma
);
static
int
pdc_sata_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
static
int
pdc_sata_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
static
void
pdc_dma_start
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc_dma_start
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc20621_dma_start
(
struct
ata_queued_cmd
*
qc
);
static
irqreturn_t
pdc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
irqreturn_t
pdc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
irqreturn_t
pdc20621_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
void
pdc_eng_timeout
(
struct
ata_port
*
ap
);
static
void
pdc_eng_timeout
(
struct
ata_port
*
ap
);
static
void
pdc_20621_phy_reset
(
struct
ata_port
*
ap
);
static
void
pdc_20621_phy_reset
(
struct
ata_port
*
ap
);
static
int
pdc_port_start
(
struct
ata_port
*
ap
);
static
int
pdc_port_start
(
struct
ata_port
*
ap
);
static
void
pdc_port_stop
(
struct
ata_port
*
ap
);
static
void
pdc_port_stop
(
struct
ata_port
*
ap
);
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc20621_fill_sg
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc_tf_load_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc_tf_load_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc_exec_command_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc_exec_command_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
);
static
inline
void
pdc_dma_complete
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
);
static
Scsi_Host_Template
pdc_sata_sht
=
{
static
Scsi_Host_Template
pdc_sata_sht
=
{
...
@@ -131,12 +146,13 @@ static struct ata_port_operations pdc_20621_ops = {
...
@@ -131,12 +146,13 @@ static struct ata_port_operations pdc_20621_ops = {
.
exec_command
=
pdc_exec_command_mmio
,
.
exec_command
=
pdc_exec_command_mmio
,
.
phy_reset
=
pdc_20621_phy_reset
,
.
phy_reset
=
pdc_20621_phy_reset
,
.
phy_config
=
pata_phy_config
,
/* not a typo */
.
phy_config
=
pata_phy_config
,
/* not a typo */
.
bmdma_start
=
pdc_dma_start
,
.
bmdma_start
=
pdc
20621
_dma_start
,
.
fill_sg
=
pdc_fill_sg
,
.
fill_sg
=
pdc
20621
_fill_sg
,
.
eng_timeout
=
pdc_eng_timeout
,
.
eng_timeout
=
pdc_eng_timeout
,
.
irq_handler
=
pdc_interrupt
,
.
irq_handler
=
pdc
20621
_interrupt
,
.
port_start
=
pdc_port_start
,
.
port_start
=
pdc_port_start
,
.
port_stop
=
pdc_port_stop
,
.
port_stop
=
pdc_port_stop
,
.
host_stop
=
pdc20621_host_stop
,
};
};
static
struct
ata_port_info
pdc_port_info
[]
=
{
static
struct
ata_port_info
pdc_port_info
[]
=
{
...
@@ -182,10 +198,8 @@ static struct pci_device_id pdc_sata_pci_tbl[] = {
...
@@ -182,10 +198,8 @@ static struct pci_device_id pdc_sata_pci_tbl[] = {
board_20319
},
board_20319
},
{
PCI_VENDOR_ID_PROMISE
,
0x3319
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
{
PCI_VENDOR_ID_PROMISE
,
0x3319
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
board_20319
},
board_20319
},
#if 0 /* broken currently */
{
PCI_VENDOR_ID_PROMISE
,
0x6622
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
{
PCI_VENDOR_ID_PROMISE
,
0x6622
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
board_20621
},
board_20621
},
#endif
{
}
/* terminate list */
{
}
/* terminate list */
};
};
...
@@ -198,6 +212,14 @@ static struct pci_driver pdc_sata_pci_driver = {
...
@@ -198,6 +212,14 @@ static struct pci_driver pdc_sata_pci_driver = {
};
};
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
)
{
void
*
mmio
=
host_set
->
private_data
;
assert
(
mmio
!=
NULL
);
iounmap
(
mmio
);
}
static
int
pdc_port_start
(
struct
ata_port
*
ap
)
static
int
pdc_port_start
(
struct
ata_port
*
ap
)
{
{
struct
pci_dev
*
pdev
=
ap
->
host_set
->
pdev
;
struct
pci_dev
*
pdev
=
ap
->
host_set
->
pdev
;
...
@@ -284,6 +306,7 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev,
...
@@ -284,6 +306,7 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev,
enum
pdc_packet_bits
{
enum
pdc_packet_bits
{
PDC_PKT_READ
=
(
1
<<
2
),
PDC_PKT_READ
=
(
1
<<
2
),
PDC_PKT_NODATA
=
(
1
<<
3
),
PDC_PKT_NODATA
=
(
1
<<
3
),
PDC20621_PKT_READ
=
(
1
<<
4
),
PDC_PKT_SIZEMASK
=
(
1
<<
7
)
|
(
1
<<
6
)
|
(
1
<<
5
),
PDC_PKT_SIZEMASK
=
(
1
<<
7
)
|
(
1
<<
6
)
|
(
1
<<
5
),
PDC_PKT_CLEAR_BSY
=
(
1
<<
4
),
PDC_PKT_CLEAR_BSY
=
(
1
<<
4
),
...
@@ -293,8 +316,9 @@ enum pdc_packet_bits {
...
@@ -293,8 +316,9 @@ enum pdc_packet_bits {
PDC_REG_DEVCTL
=
(
1
<<
3
)
|
(
1
<<
2
)
|
(
1
<<
1
),
PDC_REG_DEVCTL
=
(
1
<<
3
)
|
(
1
<<
2
)
|
(
1
<<
1
),
};
};
static
inline
void
pdc_pkt_header
(
struct
ata_taskfile
*
tf
,
dma_addr_t
sg_table
,
static
inline
unsigned
int
pdc_pkt_header
(
struct
ata_taskfile
*
tf
,
unsigned
int
devno
,
u8
*
buf
)
dma_addr_t
sg_table
,
unsigned
int
devno
,
u8
*
buf
)
{
{
u8
dev_reg
;
u8
dev_reg
;
u32
*
buf32
=
(
u32
*
)
buf
;
u32
*
buf32
=
(
u32
*
)
buf
;
...
@@ -335,9 +359,11 @@ static inline void pdc_pkt_header(struct ata_taskfile *tf, dma_addr_t sg_table,
...
@@ -335,9 +359,11 @@ static inline void pdc_pkt_header(struct ata_taskfile *tf, dma_addr_t sg_table,
/* device control register */
/* device control register */
buf
[
14
]
=
(
1
<<
5
)
|
PDC_REG_DEVCTL
;
buf
[
14
]
=
(
1
<<
5
)
|
PDC_REG_DEVCTL
;
buf
[
15
]
=
tf
->
ctl
;
buf
[
15
]
=
tf
->
ctl
;
return
16
;
/* offset of next byte */
}
}
static
inline
void
pdc_pkt_footer
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
static
inline
unsigned
int
pdc_pkt_footer
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
i
)
unsigned
int
i
)
{
{
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
...
@@ -348,19 +374,14 @@ static inline void pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
...
@@ -348,19 +374,14 @@ static inline void pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
/* and finally the command itself; also includes end-of-pkt marker */
/* and finally the command itself; also includes end-of-pkt marker */
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_LAST_REG
|
ATA_REG_CMD
;
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_LAST_REG
|
ATA_REG_CMD
;
buf
[
i
++
]
=
tf
->
command
;
buf
[
i
++
]
=
tf
->
command
;
return
i
;
}
}
static
void
pdc_prep_lba28
(
struct
ata_taskfile
*
tf
,
dma_addr_t
sg_table
,
static
inline
unsigned
int
pdc_prep_lba28
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
i
)
unsigned
int
devno
,
u8
*
buf
)
{
{
unsigned
int
i
;
pdc_pkt_header
(
tf
,
sg_table
,
devno
,
buf
);
/* the "(1 << 5)" should be read "(count << 5)" */
/* the "(1 << 5)" should be read "(count << 5)" */
i
=
16
;
/* ATA command block registers */
/* ATA command block registers */
buf
[
i
++
]
=
(
1
<<
5
)
|
ATA_REG_FEATURE
;
buf
[
i
++
]
=
(
1
<<
5
)
|
ATA_REG_FEATURE
;
buf
[
i
++
]
=
tf
->
feature
;
buf
[
i
++
]
=
tf
->
feature
;
...
@@ -377,20 +398,13 @@ static void pdc_prep_lba28(struct ata_taskfile *tf, dma_addr_t sg_table,
...
@@ -377,20 +398,13 @@ static void pdc_prep_lba28(struct ata_taskfile *tf, dma_addr_t sg_table,
buf
[
i
++
]
=
(
1
<<
5
)
|
ATA_REG_LBAH
;
buf
[
i
++
]
=
(
1
<<
5
)
|
ATA_REG_LBAH
;
buf
[
i
++
]
=
tf
->
lbah
;
buf
[
i
++
]
=
tf
->
lbah
;
pdc_pkt_footer
(
tf
,
buf
,
i
)
;
return
i
;
}
}
static
void
pdc_prep_lba48
(
struct
ata_taskfile
*
tf
,
dma_addr_t
sg_table
,
static
inline
unsigned
int
pdc_prep_lba48
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
i
)
unsigned
int
devno
,
u8
*
buf
)
{
{
unsigned
int
i
;
pdc_pkt_header
(
tf
,
sg_table
,
devno
,
buf
);
/* the "(2 << 5)" should be read "(count << 5)" */
/* the "(2 << 5)" should be read "(count << 5)" */
i
=
16
;
/* ATA command block registers */
/* ATA command block registers */
buf
[
i
++
]
=
(
2
<<
5
)
|
ATA_REG_FEATURE
;
buf
[
i
++
]
=
(
2
<<
5
)
|
ATA_REG_FEATURE
;
buf
[
i
++
]
=
tf
->
hob_feature
;
buf
[
i
++
]
=
tf
->
hob_feature
;
...
@@ -412,41 +426,299 @@ static void pdc_prep_lba48(struct ata_taskfile *tf, dma_addr_t sg_table,
...
@@ -412,41 +426,299 @@ static void pdc_prep_lba48(struct ata_taskfile *tf, dma_addr_t sg_table,
buf
[
i
++
]
=
tf
->
hob_lbah
;
buf
[
i
++
]
=
tf
->
hob_lbah
;
buf
[
i
++
]
=
tf
->
lbah
;
buf
[
i
++
]
=
tf
->
lbah
;
pdc_pkt_footer
(
tf
,
buf
,
i
)
;
return
i
;
}
}
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
)
static
inline
unsigned
int
pdc20621_pkt_header
(
struct
ata_taskfile
*
tf
,
unsigned
int
portno
,
unsigned
int
devno
,
u8
*
buf
,
unsigned
int
total_len
)
{
{
struct
pdc_port_priv
*
pp
=
qc
->
ap
->
private_data
;
u8
dev_reg
;
u32
*
buf32
=
(
u32
*
)
buf
;
unsigned
int
ofs
,
i
=
0
;
/*
* Set up Host DMA packet
*/
if
(
tf
->
protocol
==
ATA_PROT_DMA_READ
)
buf
[
i
++
]
=
PDC20621_PKT_READ
;
else
buf
[
i
++
]
=
0
;
buf
[
i
++
]
=
0
;
/* reserved */
buf
[
i
++
]
=
portno
+
1
+
4
;
/* seq. id */
buf
[
i
++
]
=
0xff
;
/* delay seq. id */
buf32
[
i
/
4
]
=
cpu_to_le32
(
PDC_20621_DIMM_BASE
+
(
4
*
1024
)
+
(
2
*
1024
*
portno
));
i
+=
4
;
buf32
[
i
/
4
]
=
cpu_to_le32
(
PDC_20621_DIMM_BASE
+
(
portno
*
1024
)
+
PDC_20621_HOST_PRD
);
i
+=
4
;
buf32
[
i
/
4
]
=
0
;
i
+=
4
;
ofs
=
PDC_20621_HOST_PRD
/
4
;
buf32
[
ofs
]
=
cpu_to_le32
(
PDC_20621_DIMM_BASE
+
(
32
*
1024
)
+
(
256
*
1024
*
portno
));
buf32
[
ofs
+
1
]
=
cpu_to_le32
(
total_len
|
ATA_PRD_EOT
);
/*
* Set up ATA packet
*/
if
(
tf
->
protocol
==
ATA_PROT_DMA_READ
)
buf
[
i
++
]
=
PDC_PKT_READ
;
else
if
(
tf
->
protocol
==
ATA_PROT_NODATA
)
buf
[
i
++
]
=
PDC_PKT_NODATA
;
else
buf
[
i
++
]
=
0
;
buf
[
i
++
]
=
0
;
/* reserved */
buf
[
i
++
]
=
portno
+
1
;
/* seq. id */
buf
[
i
++
]
=
0xff
;
/* delay seq. id */
buf32
[
i
/
4
]
=
cpu_to_le32
(
PDC_20621_DIMM_BASE
+
(
portno
*
1024
)
+
PDC_20621_ATA_PRD
);
i
+=
4
;
buf32
[
i
/
4
]
=
0
;
/* no next-packet */
i
+=
4
;
ofs
=
PDC_20621_ATA_PRD
/
4
;
buf32
[
ofs
]
=
cpu_to_le32
(
PDC_20621_DIMM_BASE
+
(
32
*
1024
)
+
(
256
*
1024
*
portno
));
buf32
[
ofs
+
1
]
=
cpu_to_le32
(
total_len
|
ATA_PRD_EOT
);
if
(
devno
==
0
)
dev_reg
=
ATA_DEVICE_OBS
;
else
dev_reg
=
ATA_DEVICE_OBS
|
ATA_DEV1
;
/* select device */
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_PKT_CLEAR_BSY
|
ATA_REG_DEVICE
;
buf
[
i
++
]
=
dev_reg
;
/* device control register */
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_REG_DEVCTL
;
buf
[
i
++
]
=
tf
->
ctl
;
return
i
;
/* offset of next byte */
}
static
void
pdc20621_fill_sg
(
struct
ata_queued_cmd
*
qc
)
{
struct
scatterlist
*
sg
=
qc
->
sg
;
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_port_priv
*
pp
=
ap
->
private_data
;
void
*
dimm_mmio
=
ap
->
host_set
->
private_data
;
unsigned
int
portno
=
ap
->
port_no
;
unsigned
int
i
,
last
,
idx
,
total_len
=
0
;
u32
*
buf
=
(
u32
*
)
&
pp
->
prd_buf
;
/*
* Build S/G table
*/
last
=
qc
->
n_elem
;
idx
=
0
;
for
(
i
=
0
;
i
<
last
;
i
++
)
{
buf
[
idx
++
]
=
cpu_to_le32
(
sg
[
i
].
dma_address
);
buf
[
idx
++
]
=
cpu_to_le32
(
sg
[
i
].
length
);
total_len
+=
sg
[
i
].
length
;
}
idx
--
;
buf
[
idx
]
|=
cpu_to_le32
(
ATA_PRD_EOT
);
/*
* Build ATA, host DMA packets
*/
i
=
pdc20621_pkt_header
(
&
qc
->
tf
,
portno
,
qc
->
dev
->
devno
,
&
pp
->
pkt_buf
[
0
],
total_len
);
ata_fill_sg
(
qc
);
if
(
qc
->
tf
.
flags
&
ATA_TFLAG_LBA48
)
if
(
qc
->
tf
.
flags
&
ATA_TFLAG_LBA48
)
pdc_prep_lba48
(
&
qc
->
tf
,
qc
->
ap
->
prd_dma
,
i
=
pdc_prep_lba48
(
&
qc
->
tf
,
&
pp
->
pkt_buf
[
0
],
i
);
qc
->
dev
->
devno
,
pp
->
pkt
);
else
else
pdc_prep_lba28
(
&
qc
->
tf
,
qc
->
ap
->
prd_dma
,
i
=
pdc_prep_lba28
(
&
qc
->
tf
,
&
pp
->
pkt_buf
[
0
],
i
);
qc
->
dev
->
devno
,
pp
->
pkt
);
i
=
pdc_pkt_footer
(
&
qc
->
tf
,
&
pp
->
pkt_buf
[
0
],
i
);
/* copy two packets and three S/G tables to DIMM MMIO window */
memcpy_toio
(
dimm_mmio
+
(
portno
*
1024
),
&
pp
->
pkt_buf
,
i
);
memcpy_toio
(
dimm_mmio
+
(
4
*
1024
)
+
(
2
*
1024
*
portno
),
buf
,
idx
*
4
);
}
static
void
pdc20621_dma_start
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_host_set
*
host_set
=
ap
->
host_set
;
unsigned
int
port_no
=
ap
->
port_no
;
void
*
mmio
=
host_set
->
mmio_base
;
unsigned
int
rw
=
(
qc
->
flags
&
ATA_QCFLAG_WRITE
);
u8
seq
=
(
u8
)
(
port_no
+
1
);
u32
pkt_addr
;
unsigned
int
doing_hdma
=
0
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
VPRINTK
(
"ENTER, ap %p, mmio %p
\n
"
,
ap
,
mmio
);
/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
if
(
rw
)
{
doing_hdma
=
1
;
seq
+=
4
;
pkt_addr
=
PDC_20621_DIMM_BASE
+
(
4
*
port_no
);
}
/* if reading, we (1) do ATA command, then (2) DMA from DIMM */
else
{
pkt_addr
=
PDC_20621_DIMM_BASE
+
(
4
*
port_no
)
+
16
;
}
wmb
();
/* flush PRD, pkt writes */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
if
(
doing_hdma
)
writel
(
pkt_addr
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
else
writel
(
pkt_addr
,
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
}
static
inline
unsigned
int
pdc20621_host_intr
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
,
unsigned
int
doing_hdma
,
void
*
mmio
)
{
unsigned
int
port_no
=
ap
->
port_no
;
u8
status
;
unsigned
int
handled
=
0
;
switch
(
qc
->
tf
.
protocol
)
{
case
ATA_PROT_DMA_READ
:
/* step two - DMA from DIMM to host */
if
(
doing_hdma
)
pdc_dma_complete
(
ap
,
qc
);
/* step one - exec ATA command */
else
{
u32
pkt_addr
=
PDC_20621_DIMM_BASE
+
(
4
*
port_no
);
u8
seq
=
(
u8
)
(
port_no
+
1
+
4
);
/* submit hdma pkt */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
writel
(
pkt_addr
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
}
handled
=
1
;
break
;
case
ATA_PROT_DMA_WRITE
:
/* step one - DMA from host to DIMM */
if
(
doing_hdma
)
{
u32
pkt_addr
=
PDC_20621_DIMM_BASE
+
(
4
*
port_no
)
+
16
;
u8
seq
=
(
u8
)
(
port_no
+
1
);
/* submit ata pkt */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
writel
(
pkt_addr
,
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
/* step two - execute ATA command */
}
else
pdc_dma_complete
(
ap
,
qc
);
handled
=
1
;
break
;
case
ATA_PROT_NODATA
:
/* command completion, but no data xfer */
status
=
ata_busy_wait
(
ap
,
ATA_BUSY
|
ATA_DRQ
,
1000
);
DPRINTK
(
"BUS_NODATA (drv_stat 0x%X)
\n
"
,
status
);
ata_qc_complete
(
qc
,
status
,
0
);
handled
=
1
;
break
;
default:
ap
->
stats
.
idle_irq
++
;
break
;
}
return
handled
;
}
}
static
inline
void
__pdc_dma_complete
(
struct
ata_port
*
ap
,
static
irqreturn_t
pdc20621_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
)
struct
ata_queued_cmd
*
qc
)
{
{
void
*
dmactl
=
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_CTLSTAT
;
struct
ata_host_set
*
host_set
=
dev_instance
;
u32
val
;
struct
ata_port
*
ap
;
u32
mask
=
0
;
unsigned
int
i
,
tmp
,
port_no
;
unsigned
int
handled
=
0
;
void
*
mmio_base
;
VPRINTK
(
"ENTER
\n
"
);
if
(
!
host_set
||
!
host_set
->
mmio_base
)
{
VPRINTK
(
"QUICK EXIT
\n
"
);
return
IRQ_NONE
;
}
mmio_base
=
host_set
->
mmio_base
;
/* reading should also clear interrupts */
mmio_base
+=
PDC_CHIP0_OFS
;
mask
=
readl
(
mmio_base
+
PDC_20621_SEQMASK
);
if
(
mask
==
0xffffffff
)
{
VPRINTK
(
"QUICK EXIT 2
\n
"
);
return
IRQ_NONE
;
}
mask
&=
0xf
;
/* only 16 tags possible */
if
(
!
mask
)
{
VPRINTK
(
"QUICK EXIT 3
\n
"
);
return
IRQ_NONE
;
}
spin_lock_irq
(
&
host_set
->
lock
);
for
(
i
=
1
;
i
<
9
;
i
++
)
{
VPRINTK
(
"port %u
\n
"
,
port_no
);
port_no
=
i
-
1
;
if
(
port_no
>
3
)
port_no
-=
4
;
if
(
port_no
>=
host_set
->
n_ports
)
ap
=
NULL
;
else
ap
=
host_set
->
ports
[
port_no
];
tmp
=
mask
&
(
1
<<
i
);
if
(
tmp
&&
ap
&&
(
!
(
ap
->
flags
&
ATA_FLAG_PORT_DISABLED
)))
{
struct
ata_queued_cmd
*
qc
;
qc
=
ata_qc_from_tag
(
ap
,
ap
->
active_tag
);
if
(
qc
&&
((
qc
->
flags
&
ATA_QCFLAG_POLL
)
==
0
))
handled
+=
pdc20621_host_intr
(
ap
,
qc
,
(
i
>
4
),
mmio_base
);
}
}
/* clear DMA start/stop bit (bit 7) */
spin_unlock_irq
(
&
host_set
->
lock
);
val
=
readl
(
dmactl
);
writel
(
val
&
~
(
1
<<
7
),
dmactl
);
VPRINTK
(
"EXIT
\n
"
);
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
return
IRQ_RETVAL
(
handled
);
ata_altstatus
(
ap
);
/* dummy read */
}
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
)
{
struct
pdc_port_priv
*
pp
=
qc
->
ap
->
private_data
;
unsigned
int
i
;
ata_fill_sg
(
qc
);
i
=
pdc_pkt_header
(
&
qc
->
tf
,
qc
->
ap
->
prd_dma
,
qc
->
dev
->
devno
,
pp
->
pkt
);
if
(
qc
->
tf
.
flags
&
ATA_TFLAG_LBA48
)
i
=
pdc_prep_lba48
(
&
qc
->
tf
,
pp
->
pkt
,
i
);
else
i
=
pdc_prep_lba28
(
&
qc
->
tf
,
pp
->
pkt
,
i
);
pdc_pkt_footer
(
&
qc
->
tf
,
pp
->
pkt
,
i
);
}
}
static
inline
void
pdc_dma_complete
(
struct
ata_port
*
ap
,
static
inline
void
pdc_dma_complete
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
)
struct
ata_queued_cmd
*
qc
)
{
{
__pdc_dma_complete
(
ap
,
qc
);
/* get drive status; clear intr; complete txn */
/* get drive status; clear intr; complete txn */
ata_qc_complete
(
ata_qc_from_tag
(
ap
,
ap
->
active_tag
),
ata_qc_complete
(
ata_qc_from_tag
(
ap
,
ap
->
active_tag
),
ata_wait_idle
(
ap
),
0
);
ata_wait_idle
(
ap
),
0
);
...
@@ -470,7 +742,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
...
@@ -470,7 +742,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
case
ATA_PROT_DMA_READ
:
case
ATA_PROT_DMA_READ
:
case
ATA_PROT_DMA_WRITE
:
case
ATA_PROT_DMA_WRITE
:
printk
(
KERN_ERR
"ata%u: DMA timeout
\n
"
,
ap
->
id
);
printk
(
KERN_ERR
"ata%u: DMA timeout
\n
"
,
ap
->
id
);
__pdc_dma_complete
(
ap
,
qc
);
ata_qc_complete
(
ata_qc_from_tag
(
ap
,
ap
->
active_tag
),
ata_qc_complete
(
ata_qc_from_tag
(
ap
,
ap
->
active_tag
),
ata_wait_idle
(
ap
)
|
ATA_ERR
,
0
);
ata_wait_idle
(
ap
)
|
ATA_ERR
,
0
);
break
;
break
;
...
@@ -532,7 +803,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
...
@@ -532,7 +803,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
struct
ata_port
*
ap
;
struct
ata_port
*
ap
;
u32
mask
=
0
;
u32
mask
=
0
;
unsigned
int
i
,
tmp
;
unsigned
int
i
,
tmp
;
unsigned
int
handled
=
0
,
have_20621
=
0
;
unsigned
int
handled
=
0
;
void
*
mmio_base
;
void
*
mmio_base
;
VPRINTK
(
"ENTER
\n
"
);
VPRINTK
(
"ENTER
\n
"
);
...
@@ -544,21 +815,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
...
@@ -544,21 +815,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
mmio_base
=
host_set
->
mmio_base
;
mmio_base
=
host_set
->
mmio_base
;
for
(
i
=
0
;
i
<
host_set
->
n_ports
;
i
++
)
{
ap
=
host_set
->
ports
[
i
];
if
(
ap
&&
(
ap
->
flags
&
PDC_FLAG_20621
))
{
have_20621
=
1
;
break
;
}
}
/* reading should also clear interrupts */
/* reading should also clear interrupts */
if
(
have_20621
)
{
mask
=
readl
(
mmio_base
+
PDC_INT_SEQMASK
);
mmio_base
+=
PDC_CHIP0_OFS
;
mask
=
readl
(
mmio_base
+
PDC_20621_SEQMASK
);
}
else
{
mask
=
readl
(
mmio_base
+
PDC_INT_SEQMASK
);
}
if
(
mask
==
0xffffffff
)
{
if
(
mask
==
0xffffffff
)
{
VPRINTK
(
"QUICK EXIT 2
\n
"
);
VPRINTK
(
"QUICK EXIT 2
\n
"
);
...
@@ -596,20 +854,12 @@ static void pdc_dma_start(struct ata_queued_cmd *qc)
...
@@ -596,20 +854,12 @@ static void pdc_dma_start(struct ata_queued_cmd *qc)
{
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_port_priv
*
pp
=
ap
->
private_data
;
struct
pdc_port_priv
*
pp
=
ap
->
private_data
;
struct
ata_host_set
*
host_set
=
ap
->
host_set
;
unsigned
int
port_no
=
ap
->
port_no
;
unsigned
int
port_no
=
ap
->
port_no
;
void
*
mmio
=
host_set
->
mmio_base
;
u8
seq
=
(
u8
)
(
port_no
+
1
);
u8
seq
=
(
u8
)
(
port_no
+
1
);
if
(
ap
->
flags
&
PDC_FLAG_20621
)
VPRINTK
(
"ENTER, ap %p
\n
"
,
ap
);
mmio
+=
PDC_CHIP0_OFS
;
VPRINTK
(
"ENTER, ap %p, mmio %p
\n
"
,
ap
,
mmio
);
writel
(
0x00000001
,
ap
->
host_set
->
mmio_base
+
(
seq
*
4
));
if
(
ap
->
flags
&
PDC_FLAG_20621
)
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
else
writel
(
0x00000001
,
mmio
+
(
seq
*
4
));
pp
->
pkt
[
2
]
=
seq
;
pp
->
pkt
[
2
]
=
seq
;
wmb
();
/* flush PRD, pkt writes */
wmb
();
/* flush PRD, pkt writes */
...
@@ -648,6 +898,14 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
...
@@ -648,6 +898,14 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
static
void
pdc_20621_init
(
struct
ata_probe_ent
*
pe
)
static
void
pdc_20621_init
(
struct
ata_probe_ent
*
pe
)
{
{
u32
tmp
;
void
*
mmio
=
pe
->
mmio_base
;
mmio
+=
PDC_CHIP0_OFS
;
tmp
=
readl
(
mmio
+
PDC_20621_DIMM_WINDOW
)
&
0xffff0000
;
tmp
|=
0x40
;
/* page 40h; arbitrarily selected */
writel
(
tmp
,
mmio
+
PDC_20621_DIMM_WINDOW
);
}
}
static
void
pdc_host_init
(
unsigned
int
chip_id
,
struct
ata_probe_ent
*
pe
)
static
void
pdc_host_init
(
unsigned
int
chip_id
,
struct
ata_probe_ent
*
pe
)
...
@@ -691,8 +949,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -691,8 +949,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
static
int
printed_version
;
static
int
printed_version
;
struct
ata_probe_ent
*
probe_ent
=
NULL
;
struct
ata_probe_ent
*
probe_ent
=
NULL
;
unsigned
long
base
;
unsigned
long
base
;
void
*
mmio_base
;
void
*
mmio_base
,
*
dimm_mmio
=
NULL
;
unsigned
int
board_idx
=
(
unsigned
int
)
ent
->
driver_data
;
unsigned
int
board_idx
=
(
unsigned
int
)
ent
->
driver_data
;
unsigned
int
have_20621
=
(
board_idx
==
board_20621
);
int
rc
;
int
rc
;
if
(
!
printed_version
++
)
if
(
!
printed_version
++
)
...
@@ -732,6 +991,15 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -732,6 +991,15 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
}
}
base
=
(
unsigned
long
)
mmio_base
;
base
=
(
unsigned
long
)
mmio_base
;
if
(
have_20621
)
{
dimm_mmio
=
ioremap
(
pci_resource_start
(
pdev
,
4
),
pci_resource_len
(
pdev
,
4
));
if
(
!
dimm_mmio
)
{
rc
=
-
ENOMEM
;
goto
err_out_iounmap
;
}
}
probe_ent
->
sht
=
pdc_port_info
[
board_idx
].
sht
;
probe_ent
->
sht
=
pdc_port_info
[
board_idx
].
sht
;
probe_ent
->
host_flags
=
pdc_port_info
[
board_idx
].
host_flags
;
probe_ent
->
host_flags
=
pdc_port_info
[
board_idx
].
host_flags
;
probe_ent
->
pio_mask
=
pdc_port_info
[
board_idx
].
pio_mask
;
probe_ent
->
pio_mask
=
pdc_port_info
[
board_idx
].
pio_mask
;
...
@@ -742,8 +1010,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -742,8 +1010,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent
->
irq_flags
=
SA_SHIRQ
;
probe_ent
->
irq_flags
=
SA_SHIRQ
;
probe_ent
->
mmio_base
=
mmio_base
;
probe_ent
->
mmio_base
=
mmio_base
;
if
(
board_idx
==
board_20621
)
if
(
have_20621
)
{
probe_ent
->
private_data
=
dimm_mmio
;
base
+=
PDC_CHIP0_OFS
;
base
+=
PDC_CHIP0_OFS
;
}
pdc_sata_setup_port
(
&
probe_ent
->
port
[
0
],
base
+
0x200
);
pdc_sata_setup_port
(
&
probe_ent
->
port
[
0
],
base
+
0x200
);
probe_ent
->
port
[
0
].
scr_addr
=
base
+
0x400
;
probe_ent
->
port
[
0
].
scr_addr
=
base
+
0x400
;
...
@@ -774,15 +1044,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -774,15 +1044,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pci_set_master
(
pdev
);
pci_set_master
(
pdev
);
/* initialize adapter */
/* initialize adapter */
switch
(
board_idx
)
{
if
(
have_20621
)
case
board_20621
:
pdc_20621_init
(
probe_ent
);
pdc_20621_init
(
probe_ent
);
break
;
else
default:
pdc_host_init
(
board_idx
,
probe_ent
);
pdc_host_init
(
board_idx
,
probe_ent
);
break
;
}
/* FIXME: check ata_device_add return value */
/* FIXME: check ata_device_add return value */
ata_device_add
(
probe_ent
);
ata_device_add
(
probe_ent
);
...
@@ -790,6 +1055,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -790,6 +1055,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return
0
;
return
0
;
err_out_iounmap:
iounmap
(
mmio_base
);
err_out_free_ent:
err_out_free_ent:
kfree
(
probe_ent
);
kfree
(
probe_ent
);
err_out_regions:
err_out_regions:
...
@@ -800,7 +1067,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
...
@@ -800,7 +1067,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
}
}
static
int
__init
pdc_sata_init
(
void
)
static
int
__init
pdc_sata_init
(
void
)
{
{
int
rc
;
int
rc
;
...
...
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