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
00e7ed4d
Commit
00e7ed4d
authored
Sep 11, 2002
by
Jens Axboe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cs5530 update
parent
563cbaa6
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
210 additions
and
78 deletions
+210
-78
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5530.c
+154
-78
drivers/ide/pci/cs5530.h
drivers/ide/pci/cs5530.h
+56
-0
No files found.
drivers/ide/pci/cs5530.c
View file @
00e7ed4d
...
...
@@ -28,15 +28,14 @@
#include <asm/irq.h>
#include "ide_modes.h"
#define DISPLAY_CS5530_TIMINGS
#include "cs5530.h"
#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static
int
cs5530_get_info
(
char
*
,
char
**
,
off_t
,
int
)
;
extern
int
(
*
cs5530_display_info
)(
char
*
,
char
**
,
off_t
,
int
);
/* ide-proc.c */
static
u8
cs5530_proc
=
0
;
static
struct
pci_dev
*
bmide_dev
;
static
int
cs5530_get_info
(
char
*
buffer
,
char
**
addr
,
off_t
offset
,
int
count
)
...
...
@@ -50,8 +49,8 @@ static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count)
* to investigate:
*/
c0
=
inb_p
((
u
nsigned
short
)
bibma
+
0x02
);
c1
=
inb_p
((
u
nsigned
short
)
bibma
+
0x0a
);
c0
=
inb_p
((
u
16
)
bibma
+
0x02
);
c1
=
inb_p
((
u
16
)
bibma
+
0x0a
);
p
+=
sprintf
(
p
,
"
\n
"
"Cyrix 5530 Chipset.
\n
"
);
...
...
@@ -66,8 +65,10 @@ static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count)
"-------- drive0 ---------- drive1 ------
\n
"
);
p
+=
sprintf
(
p
,
"DMA enabled: %s %s "
" %s %s
\n
"
,
(
c0
&
0x20
)
?
"yes"
:
"no "
,
(
c0
&
0x40
)
?
"yes"
:
"no "
,
(
c1
&
0x20
)
?
"yes"
:
"no "
,
(
c1
&
0x40
)
?
"yes"
:
"no "
);
(
c0
&
0x20
)
?
"yes"
:
"no "
,
(
c0
&
0x40
)
?
"yes"
:
"no "
,
(
c1
&
0x20
)
?
"yes"
:
"no "
,
(
c1
&
0x40
)
?
"yes"
:
"no "
);
p
+=
sprintf
(
p
,
"UDMA
\n
"
);
p
+=
sprintf
(
p
,
"DMA
\n
"
);
...
...
@@ -77,14 +78,18 @@ static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count)
}
#endif
/* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
byte
cs5530_proc
=
0
;
/*
* Set a new transfer mode at the drive
/**
* cs5530_xfer_set_mode - set a new transfer mode at the drive
* @drive: drive to tune
* @mode: new mode
*
* Logging wrapper to the IDE driver speed configuration. This can
* probably go away now.
*/
int
cs5530_set_xfer_mode
(
ide_drive_t
*
drive
,
byte
mode
)
static
int
cs5530_set_xfer_mode
(
ide_drive_t
*
drive
,
u8
mode
)
{
printk
(
"%s: cs5530_set_xfer_mode(%s)
\n
"
,
printk
(
KERN_DEBUG
"%s: cs5530_set_xfer_mode(%s)
\n
"
,
drive
->
name
,
ide_xfer_verbose
(
mode
));
return
(
ide_config_drive_speed
(
drive
,
mode
));
}
...
...
@@ -94,9 +99,10 @@ int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode)
* Format-0 uses fast data reg timings, with slower command reg timings.
* Format-1 uses fast timings for all registers, but won't work with all drives.
*/
static
unsigned
int
cs5530_pio_timings
[
2
][
5
]
=
{{
0x00009172
,
0x00012171
,
0x00020080
,
0x00032010
,
0x00040010
},
{
0xd1329172
,
0x71212171
,
0x30200080
,
0x20102010
,
0x00100010
}};
static
unsigned
int
cs5530_pio_timings
[
2
][
5
]
=
{
{
0x00009172
,
0x00012171
,
0x00020080
,
0x00032010
,
0x00040010
},
{
0xd1329172
,
0x71212171
,
0x30200080
,
0x20102010
,
0x00100010
}
};
/*
* After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
...
...
@@ -104,32 +110,41 @@ static unsigned int cs5530_pio_timings[2][5] =
#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
/*
/**
* cs5530_tuneproc - select/set PIO modes
*
* cs5530_tuneproc() handles selection/setting of PIO modes
* for both the chipset and drive.
*
* The ide_init_cs5530() routine guarantees that all drives
* will have valid default PIO timings set up before we get here.
*/
static
void
cs5530_tuneproc
(
ide_drive_t
*
drive
,
byte
pio
)
/* pio=255 means "autotune" */
static
void
cs5530_tuneproc
(
ide_drive_t
*
drive
,
u8
pio
)
/* pio=255 means "autotune" */
{
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
unsigned
int
format
,
basereg
=
CS5530_BASEREG
(
hwif
);
static
byte
modes
[
5
]
=
{
XFER_PIO_0
,
XFER_PIO_1
,
XFER_PIO_2
,
XFER_PIO_3
,
XFER_PIO_4
};
static
u8
modes
[
5
]
=
{
XFER_PIO_0
,
XFER_PIO_1
,
XFER_PIO_2
,
XFER_PIO_3
,
XFER_PIO_4
};
pio
=
ide_get_best_pio_mode
(
drive
,
pio
,
4
,
NULL
);
if
(
!
cs5530_set_xfer_mode
(
drive
,
modes
[
pio
]))
{
format
=
(
inl
(
basereg
+
4
)
>>
31
)
&
1
;
outl
(
cs5530_pio_timings
[
format
][
pio
],
format
=
(
hwif
->
INL
(
basereg
+
4
)
>>
31
)
&
1
;
hwif
->
OUTL
(
cs5530_pio_timings
[
format
][
pio
],
basereg
+
(
drive
->
select
.
b
.
unit
<<
3
));
}
}
#ifdef CONFIG_BLK_DEV_IDEDMA
/*
/**
* cs5530_config_dma - select/set DMA and UDMA modes
* @drive: drive to tune
*
* cs5530_config_dma() handles selection/setting of DMA/UDMA modes
* for both the chipset and drive.
* for both the chipset and drive. The CS5530 has limitations about
* mixing DMA/UDMA on the same cable.
*/
static
int
cs5530_config_dma
(
ide_drive_t
*
drive
)
{
int
udma_ok
=
1
,
mode
=
0
;
...
...
@@ -142,9 +157,9 @@ static int cs5530_config_dma (ide_drive_t *drive)
/*
* Default to DMA-off in case we run into trouble here.
*/
(
void
)
hwif
->
dmaproc
(
ide_dma_off_quietly
,
drive
);
hwif
->
ide_dma_off_quietly
(
drive
);
/* turn off DMA while we fiddle */
(
void
)
hwif
->
dmaproc
(
ide_dma_host_off
,
drive
);
hwif
->
ide_dma_host_off
(
drive
);
/* clear DMA_capable bit */
/*
...
...
@@ -155,11 +170,14 @@ static int cs5530_config_dma (ide_drive_t *drive)
* but that might be a bit confusing. So, for now we statically
* handle this requirement by looking at our mate drive to see
* what it is capable of, before choosing a mode for our own drive.
*
* Note: This relies on the fact we never fail from UDMA to MWDMA_2
* but instead drop to PIO
*/
if
(
mate
->
present
)
{
struct
hd_driveid
*
mateid
=
mate
->
id
;
if
(
mateid
&&
(
mateid
->
capability
&
1
)
&&
!
hwif
->
dmaproc
(
ide_dma_bad_drive
,
mate
))
{
!
hwif
->
ide_dma_bad_drive
(
mate
))
{
if
((
mateid
->
field_valid
&
4
)
&&
(
mateid
->
dma_ultra
&
7
))
udma_ok
=
1
;
...
...
@@ -175,8 +193,8 @@ static int cs5530_config_dma (ide_drive_t *drive)
* Now see what the current drive is capable of,
* selecting UDMA only if the mate said it was ok.
*/
if
(
id
&&
(
id
->
capability
&
1
)
&&
hwif
->
autodma
&&
!
hwif
->
dmaproc
(
ide_dma_bad_drive
,
drive
))
{
if
(
id
&&
(
id
->
capability
&
1
)
&&
drive
->
autodma
&&
!
hwif
->
ide_dma_bad_drive
(
drive
))
{
if
(
udma_ok
&&
(
id
->
field_valid
&
4
)
&&
(
id
->
dma_ultra
&
7
))
{
if
(
id
->
dma_ultra
&
4
)
mode
=
XFER_UDMA_2
;
...
...
@@ -212,64 +230,51 @@ static int cs5530_config_dma (ide_drive_t *drive)
case
XFER_MW_DMA_1
:
timings
=
0x00012121
;
break
;
case
XFER_MW_DMA_2
:
timings
=
0x00002020
;
break
;
default:
printk
(
"%s: cs5530_config_dma: huh? mode=%02x
\n
"
,
printk
(
KERN_ERR
"%s: cs5530_config_dma: huh? mode=%02x
\n
"
,
drive
->
name
,
mode
);
return
1
;
/* failure */
}
basereg
=
CS5530_BASEREG
(
hwif
);
reg
=
inl
(
basereg
+
4
);
/* get drive0 config register */
reg
=
hwif
->
INL
(
basereg
+
4
);
/* get drive0 config register */
timings
|=
reg
&
0x80000000
;
/* preserve PIO format bit */
if
(
unit
==
0
)
{
/* are we configuring drive0? */
outl
(
timings
,
basereg
+
4
);
/* write drive0 config register */
hwif
->
OUTL
(
timings
,
basereg
+
4
);
/* write drive0 config register */
}
else
{
if
(
timings
&
0x00100000
)
reg
|=
0x00100000
;
/* enable UDMA timings for both drives */
else
reg
&=
~
0x00100000
;
/* disable UDMA timings for both drives */
outl
(
reg
,
basereg
+
4
);
/* write drive0 config register */
outl
(
timings
,
basereg
+
12
);
/* write drive1 config register */
hwif
->
OUTL
(
reg
,
basereg
+
4
);
/* write drive0 config register */
hwif
->
OUTL
(
timings
,
basereg
+
12
);
/* write drive1 config register */
}
(
void
)
hwif
->
dmaproc
(
ide_dma_host_on
,
drive
);
(
void
)
hwif
->
ide_dma_host_on
(
drive
);
/* set DMA_capable bit */
/*
* Finally, turn DMA on in software, and exit.
*/
return
hwif
->
dmaproc
(
ide_dma_on
,
drive
);
/* success */
}
/*
* This is a CS5530-specific wrapper for the standard ide_dmaproc().
* We need it for our custom "ide_dma_check" function.
* All other requests are forwarded to the standard ide_dmaproc().
*/
int
cs5530_dmaproc
(
ide_dma_action_t
func
,
ide_drive_t
*
drive
)
{
switch
(
func
)
{
case
ide_dma_check
:
return
cs5530_config_dma
(
drive
);
default:
break
;
}
/* Other cases are done by generic IDE-DMA code. */
return
ide_dmaproc
(
func
,
drive
);
return
hwif
->
ide_dma_on
(
drive
);
/* success */
}
#endif
/* CONFIG_BLK_DEV_IDEDMA */
/*
/**
* init_chipset_5530 - set up 5530 bridge
* @dev: PCI device
* @name: device name
*
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
unsigned
int
__init
pci_init_cs5530
(
struct
pci_dev
*
dev
,
const
char
*
name
)
static
unsigned
int
__init
init_chipset_cs5530
(
struct
pci_dev
*
dev
,
const
char
*
name
)
{
struct
pci_dev
*
master_0
=
NULL
,
*
cs5530_0
=
NULL
;
unsigned
short
pcicmd
=
0
;
unsigned
long
flags
;
#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
if
(
!
cs5530_proc
)
{
cs5530_proc
=
1
;
bmide_dev
=
dev
;
cs5530_display_info
=
&
cs5530_get_info
;
ide_pci_register_host_proc
(
&
cs5530_procs
[
0
])
;
}
#endif
/* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
...
...
@@ -286,11 +291,11 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
}
}
if
(
!
master_0
)
{
printk
(
"%s: unable to locate PCI MASTER function
\n
"
,
name
);
printk
(
KERN_ERR
"%s: unable to locate PCI MASTER function
\n
"
,
name
);
return
0
;
}
if
(
!
cs5530_0
)
{
printk
(
"%s: unable to locate CS5530 LEGACY function
\n
"
,
name
);
printk
(
KERN_ERR
"%s: unable to locate CS5530 LEGACY function
\n
"
,
name
);
return
0
;
}
...
...
@@ -301,19 +306,22 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
* Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
* --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
*/
pci_read_config_word
(
cs5530_0
,
PCI_COMMAND
,
&
pcicmd
);
pci_write_config_word
(
cs5530_0
,
PCI_COMMAND
,
pcicmd
|
PCI_COMMAND_MASTER
|
PCI_COMMAND_INVALIDATE
);
pci_set_master
(
cs5530_0
);
pci_set_mwi
(
cs5530_0
);
/*
* Set PCI CacheLineSize to 16-bytes:
* --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
*/
pci_write_config_byte
(
cs5530_0
,
PCI_CACHE_LINE_SIZE
,
0x04
);
/*
* Disable trapping of UDMA register accesses (Win98 hack):
* --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
*/
pci_write_config_word
(
cs5530_0
,
0xd0
,
0x5006
);
/*
...
...
@@ -321,6 +329,7 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
* The other settings are what is necessary to get the register
* into a sane state for IDE DMA operation.
*/
pci_write_config_byte
(
master_0
,
0x40
,
0x1e
);
/*
...
...
@@ -332,12 +341,14 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
* 512bytes: OR 0x08 at 0x41
* 1024bytes: OR 0x0c at 0x41
*/
pci_write_config_byte
(
master_0
,
0x41
,
0x14
);
/*
* These settings are necessary to get the chip
* into a sane state for IDE DMA operation.
*/
pci_write_config_byte
(
master_0
,
0x42
,
0x00
);
pci_write_config_byte
(
master_0
,
0x43
,
0xc1
);
...
...
@@ -346,11 +357,15 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
return
0
;
}
/*
* This gets invoked by the IDE driver once for each channel,
* and performs channel-specific pre-initialization before drive probing.
/**
* init_hwif_cs5530 - initialise an IDE channel
* @hwif: IDE to initialize
*
* This gets invoked by the IDE driver once for each channel. It
* performs channel-specific pre-initialization before drive probing.
*/
void
__init
ide_init_cs5530
(
ide_hwif_t
*
hwif
)
static
void
__init
init_hwif_cs5530
(
ide_hwif_t
*
hwif
)
{
unsigned
int
basereg
,
d0_timings
;
hwif
->
autodma
=
0
;
...
...
@@ -360,27 +375,88 @@ void __init ide_init_cs5530 (ide_hwif_t *hwif)
hwif
->
tuneproc
=
&
cs5530_tuneproc
;
basereg
=
CS5530_BASEREG
(
hwif
);
d0_timings
=
inl
(
basereg
+
0
);
d0_timings
=
hwif
->
INL
(
basereg
+
0
);
if
(
CS5530_BAD_PIO
(
d0_timings
))
{
/* PIO timings not initialized? */
outl
(
cs5530_pio_timings
[(
d0_timings
>>
31
)
&
1
][
0
],
basereg
+
0
);
hwif
->
OUTL
(
cs5530_pio_timings
[(
d0_timings
>>
31
)
&
1
][
0
],
basereg
+
0
);
if
(
!
hwif
->
drives
[
0
].
autotune
)
hwif
->
drives
[
0
].
autotune
=
1
;
/* needs autotuning later */
}
if
(
CS5530_BAD_PIO
(
inl
(
basereg
+
8
)))
{
if
(
CS5530_BAD_PIO
(
hwif
->
INL
(
basereg
+
8
)))
{
/* PIO timings not initialized? */
outl
(
cs5530_pio_timings
[(
d0_timings
>>
31
)
&
1
][
0
],
basereg
+
8
);
hwif
->
OUTL
(
cs5530_pio_timings
[(
d0_timings
>>
31
)
&
1
][
0
],
basereg
+
8
);
if
(
!
hwif
->
drives
[
1
].
autotune
)
hwif
->
drives
[
1
].
autotune
=
1
;
/* needs autotuning later */
}
hwif
->
atapi_dma
=
1
;
hwif
->
ultra_mask
=
0x07
;
hwif
->
mwdma_mask
=
0x07
;
#ifdef CONFIG_BLK_DEV_IDEDMA
hwif
->
dmaproc
=
&
cs5530_dmaproc
;
#ifdef CONFIG_IDEDMA_AUTO
hwif
->
ide_dma_check
=
&
cs5530_config_dma
;
if
(
!
noautodma
)
hwif
->
autodma
=
1
;
#endif
/* CONFIG_IDEDMA_AUTO */
hwif
->
drives
[
0
].
autodma
=
hwif
->
autodma
;
hwif
->
drives
[
1
].
autodma
=
hwif
->
autodma
;
#endif
/* CONFIG_BLK_DEV_IDEDMA */
}
/**
* init_dma_cs5530 - set up for DMA
* @hwif: interface
* @dmabase: DMA base address
*
* FIXME: this can go away
*/
static
void
__init
init_dma_cs5530
(
ide_hwif_t
*
hwif
,
unsigned
long
dmabase
)
{
ide_setup_dma
(
hwif
,
dmabase
,
8
);
}
extern
void
ide_setup_pci_device
(
struct
pci_dev
*
,
ide_pci_device_t
*
);
/**
* init_setup_cs5530 - set up a CS5530 IDE
* @dev: PCI device
* @d: PCI ide device info
*
* FIXME: this function can go away too
*/
static
void
__init
init_setup_cs5530
(
struct
pci_dev
*
dev
,
ide_pci_device_t
*
d
)
{
ide_setup_pci_device
(
dev
,
d
);
}
/**
* cs5530_scan_pcidev - set up any CS5530 device
* @dev: pci device to check
*
* Check if the device is a 5530 IDE controller. If it is then
* claim and set up the interface. Return 1 if we claimed the
* interface or zero if it is not ours
*/
int
__init
cs5530_scan_pcidev
(
struct
pci_dev
*
dev
)
{
ide_pci_device_t
*
d
;
if
(
dev
->
vendor
!=
PCI_VENDOR_ID_CYRIX
)
return
0
;
for
(
d
=
cs5530_chipsets
;
d
&&
d
->
vendor
&&
d
->
device
;
++
d
)
{
if
(((
d
->
vendor
==
dev
->
vendor
)
&&
(
d
->
device
==
dev
->
device
))
&&
(
d
->
init_setup
))
{
d
->
init_setup
(
dev
,
d
);
return
1
;
}
}
return
0
;
}
drivers/ide/pci/cs5530.h
0 → 100644
View file @
00e7ed4d
#ifndef CS5530_H
#define CS5530_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_CS5530_TIMINGS
#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static
u8
cs5530_proc
;
static
int
cs5530_get_info
(
char
*
,
char
**
,
off_t
,
int
);
static
ide_pci_host_proc_t
cs5530_procs
[]
__initdata
=
{
{
name:
"cs5530"
,
set:
1
,
get_info:
cs5530_get_info
,
parent:
NULL
,
},
};
#endif
/* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
static
void
init_setup_cs5530
(
struct
pci_dev
*
,
ide_pci_device_t
*
);
static
unsigned
int
init_chipset_cs5530
(
struct
pci_dev
*
,
const
char
*
);
static
void
init_hwif_cs5530
(
ide_hwif_t
*
);
static
void
init_dma_cs5530
(
ide_hwif_t
*
,
unsigned
long
);
static
ide_pci_device_t
cs5530_chipsets
[]
__initdata
=
{
{
vendor:
PCI_VENDOR_ID_CYRIX
,
device:
PCI_DEVICE_ID_CYRIX_5530_IDE
,
name:
"CS5530"
,
init_setup:
init_setup_cs5530
,
init_chipset:
init_chipset_cs5530
,
init_iops:
NULL
,
init_hwif:
init_hwif_cs5530
,
init_dma:
init_dma_cs5530
,
channels:
2
,
autodma:
AUTODMA
,
enablebits:
{{
0x00
,
0x00
,
0x00
},
{
0x00
,
0x00
,
0x00
}},
bootable:
ON_BOARD
,
extra:
0
,
},{
vendor:
0
,
device:
0
,
channels:
0
,
bootable:
EOL
,
}
};
#endif
/* CS5530_H */
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